├── .gitignore ├── LICENSE ├── README.md ├── demo ├── controllers │ └── demo.js ├── index.html ├── resources │ └── styles │ │ └── demo.css └── views │ ├── item-1-1.html │ ├── item-1-2.html │ ├── item-2.html │ ├── item-3-1.html │ ├── item-3-2-1.html │ ├── item-3-2-2-1.html │ ├── item-4-1.html │ ├── item-4-2.html │ ├── item-4.html │ └── readme.html ├── package.json └── source ├── Makefile ├── angular-material-multilevel-menu.css ├── angular-material-multilevel-menu.html └── angular-material-multilevel-menu.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | yarn.lock 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Juan Manuel Mouriz 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # angular-material-multilevel-menu 2 | 3 | Material Multi-Level Menu for AngularJS 4 | 5 | ## Demo 6 | 7 | View [online demo](https://jmouriz.github.io/angular-material-multilevel-menu/demo/demo.html) 8 | 9 | ## Main features 10 | 11 | - Breadcrumb 12 | - Interface with angular-route if available 13 | 14 | ## Install 15 | 16 | Download the package: 17 | 18 | ``` 19 | yarn add angular-material-multilevel-menu 20 | ``` 21 | 22 | ## Dependencies 23 | 24 | TODO 25 | 26 | ## Usage 27 | 28 | In your document head, include: 29 | 30 | ```html 31 | 32 | ``` 33 | 34 | Use the md-multi-level-menu where you wish: 35 | 36 | ```html 37 | 40 | 41 | ``` 42 | 43 | Then, just before close body tag, include: 44 | 45 | ```html 46 | 47 | ``` 48 | 49 | Include the module in your application: 50 | 51 | ```javascript 52 | var application = angular.module('Application', ['ngMdMultiLevelMenu']); 53 | ``` 54 | 55 | Configure the items: 56 | 57 | ```javascript 58 | application.config(['menuProvider', function(menuProvider) { 59 | menuProvider.items([{ 60 | label: 'Item 1', 61 | icon: 'amazon', 62 | items: [{ 63 | label: 'Item 1.1', 64 | link: 'item-1-1', 65 | icon: 'apple' 66 | }, { 67 | label: 'Item 1.2', 68 | link: 'item-1-2', 69 | icon: 'facebook' 70 | }] 71 | }, { 72 | label: 'Item 2', 73 | link: 'item-2', 74 | icon: 'windows' 75 | }, { 76 | label: 'Item 3', 77 | icon: 'google-plus', 78 | items: [{ 79 | label: 'Item 3.1', 80 | link: 'item-3-1', 81 | icon: 'twitter' 82 | }, { 83 | label: 'Item 3.2', 84 | icon: 'github-box', 85 | items: [{ 86 | label: 'Item 3.2.1', 87 | link: 'item-3-2-1', 88 | icon: 'whatsapp' 89 | }, { 90 | label: 'Item 3.2.2', 91 | icon: 'office', 92 | items: [{ 93 | label: 'Item 3.2.2.1', 94 | link: 'item-3-2-2-1', 95 | icon: 'hangouts' 96 | }] 97 | }] 98 | }] 99 | }, { 100 | label: 'Item 4', 101 | link: 'item-4', 102 | icon: 'linkedin' 103 | hidden: false 104 | }]); 105 | }]); 106 | ``` 107 | 108 | Finally, in your controller, configure the select callback of $menu service to handle the links: 109 | 110 | ```javascript 111 | application.controller('Controller', ['$menu', function($menu) { 112 | $menu.callback(function(item) { 113 | console.log('You are going to', item.link); 114 | }); 115 | }]); 116 | ``` 117 | 118 | ## Development install 119 | 120 | ``` 121 | git clone https://github.com/jmouriz/angular-material-multilevel-menu.git 122 | cd angular-material-multilevel-menu 123 | yarn install 124 | cd source 125 | make 126 | ``` 127 | 128 | TODO 129 | -------------------------------------------------------------------------------- /demo/controllers/demo.js: -------------------------------------------------------------------------------- 1 | var $DEBUG = {}; 2 | 3 | var demo = angular.module('Demo', ['ngMaterial', 'ngMdMultiLevelMenu', 'ngMdBadge', 'ngRoute', 'hc.marked']); 4 | 5 | demo.config(['menuProvider', function(menuProvider) { 6 | menuProvider.items('primary', [{ 7 | label: 'Documentation', 8 | icon: 'import_contacts', 9 | link: 'demo/views/readme', 10 | color: 'blue' 11 | }, { 12 | id: 'item-1', 13 | label: 'Item 1: 3', 14 | icon: 'amazon', 15 | items: [{ 16 | label: 'Item 1.1', 17 | link: 'demo/views/item-1-1', 18 | icon: 'apple' 19 | }, { 20 | label: 'Item 1.2', 21 | link: 'demo/views/item-1-2', 22 | icon: 'facebook' 23 | }] 24 | }, { 25 | id: 'item-2', 26 | label: 'Item 2', 27 | link: 'demo/views/item-2', 28 | icon: 'windows', 29 | badge: 3 30 | }, { 31 | label: 'Item 3', 32 | icon: 'google-plus', 33 | items: [{ 34 | label: 'Item 3.1', 35 | link: 'demo/views/item-3-1', 36 | icon: 'twitter' 37 | }, { 38 | label: 'Item 3.2', 39 | icon: 'github-box', 40 | items: [{ 41 | label: 'Item 3.2.1', 42 | link: 'demo/views/item-3-2-1', 43 | icon: 'whatsapp' 44 | }, { 45 | label: 'Item 3.2.2', 46 | icon: 'office', 47 | items: [{ 48 | label: 'Item 3.2.2.1', 49 | link: 'demo/views/item-3-2-2-1', 50 | icon: 'hangouts' 51 | }] 52 | }] 53 | }] 54 | }, { 55 | id: 'item-4', 56 | label: 'Item 4', 57 | link: 'demo/views/item-4', 58 | icon: 'linkedin' 59 | }]); 60 | 61 | menuProvider.items('secondary', [{ 62 | label: 'Documentation X', 63 | icon: 'import_contacts', 64 | link: 'demo/views/readme', 65 | color: 'blue' 66 | }, { 67 | id: 'item-1', 68 | label: 'Item 1: 3', 69 | icon: 'amazon', 70 | items: [{ 71 | label: 'Item 1.1', 72 | link: 'demo/views/item-1-1', 73 | icon: 'apple' 74 | }, { 75 | label: 'Item 1.2', 76 | link: 'demo/views/item-1-2', 77 | icon: 'facebook' 78 | }] 79 | }, { 80 | id: 'item-2', 81 | label: 'Item 2', 82 | link: 'demo/views/item-2', 83 | icon: 'windows', 84 | badge: 3 85 | }, { 86 | label: 'Item 3', 87 | icon: 'google-plus', 88 | items: [{ 89 | label: 'Item 3.1', 90 | link: 'demo/views/item-3-1', 91 | icon: 'twitter' 92 | }, { 93 | label: 'Item 3.2', 94 | icon: 'github-box', 95 | items: [{ 96 | label: 'Item 3.2.1', 97 | link: 'demo/views/item-3-2-1', 98 | icon: 'whatsapp' 99 | }, { 100 | label: 'Item 3.2.2', 101 | icon: 'office', 102 | items: [{ 103 | label: 'Item 3.2.2.1', 104 | link: 'demo/views/item-3-2-2-1', 105 | icon: 'hangouts' 106 | }] 107 | }] 108 | }] 109 | }, { 110 | id: 'item-4', 111 | label: 'Item 4', 112 | link: 'demo/views/item-4', 113 | icon: 'linkedin' 114 | }]); 115 | }]); 116 | 117 | demo.config(['markedProvider', function(markedProvider) { 118 | markedProvider.setOptions({ 119 | gfm: true, 120 | tables: true, 121 | highlight: function(code, language) { 122 | if (!language) { 123 | language = 'bash'; 124 | } else if (language == 'html') { 125 | language = 'markup'; 126 | } 127 | return Prism.highlight(code, Prism.languages[language]); 128 | } 129 | }); 130 | }]); 131 | 132 | demo.controller('Demo', ['$scope', '$menu', '$mdSidenav', '$mdBottomSheet', function($scope, $menu, $mdSidenav, $mdBottomSheet) { 133 | $scope.breadcrumb = $menu.breadcrumb(); 134 | $scope.style = $menu.style(); 135 | //$scope.count = $menu.get('item-2').badge; 136 | 137 | $scope.toggle = function() { 138 | $mdSidenav('left').toggle(); 139 | $scope.icon = $scope.icon == 'menu' ? 'close' : 'menu'; 140 | }; 141 | 142 | $scope.test = function() { 143 | var item = $menu.get('primary', 'item-4'); 144 | $DEBUG.menu = $menu; 145 | if (item.items) { 146 | item.items = undefined; 147 | } else { 148 | item.items = [{ 149 | label: 'Item 4.1', 150 | link: 'demo/views/item-4-1', 151 | icon: 'favorite' 152 | }, { 153 | label: 'Item 4.2', 154 | link: 'demo/views/item-4-2', 155 | icon: 'grade' 156 | }] 157 | } 158 | }; 159 | 160 | $scope.menu = function() { 161 | $mdBottomSheet.show({ 162 | templateUrl: 'bottom-sheet-template', 163 | controller: function($scope) {} 164 | }); 165 | }; 166 | 167 | $menu.callback(function(item) { 168 | $scope.toggle(); 169 | if (item.link) { 170 | console.log('You are going to', item.link); 171 | $mdBottomSheet.hide(); 172 | } 173 | }); 174 | 175 | $mdSidenav('left', true).then(function(instance) { 176 | $scope.icon = 'menu'; 177 | instance.onClose(function () { 178 | $scope.icon = 'menu'; 179 | }); 180 | }); 181 | 182 | $scope.$watch('count', function(value) { 183 | //$menu.get('item-2').badge = $scope.count; 184 | //$menu.get('item-1').label = 'Item 1: ' + $scope.count; 185 | }); 186 | 187 | $scope.$watch('breadcrumb', function(value) { 188 | $menu.breadcrumb(value); 189 | }); 190 | 191 | $scope.$watch('style', function(value) { 192 | $menu.style(value); 193 | }); 194 | }]); 195 | -------------------------------------------------------------------------------- /demo/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | AngularJS Material Multi Level Menu Demo 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 |

AngularJS Multilevel Menu Demo

23 |
24 |
25 | 26 | 27 | 32 | 33 | 34 | 35 | 36 | 37 | Replace 38 | Accordion 39 | 40 | 41 | Show breadcrumb 42 | 43 | 44 | 45 | Dynamic test 46 | 47 | Bottom bar 48 | 49 | 50 | 51 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /demo/resources/styles/demo.css: -------------------------------------------------------------------------------- 1 | md-sidenav { 2 | position: static; 3 | } 4 | 5 | md-bottom-sheet { 6 | overflow: hidden; 7 | padding-top: 0; 8 | padding-left: 0; 9 | padding-right: 0; 10 | } 11 | 12 | .content { 13 | padding: 16px; 14 | } 15 | 16 | pre { 17 | word-wrap: break-word; 18 | white-space: pre-wrap; 19 | } 20 | -------------------------------------------------------------------------------- /demo/views/item-1-1.html: -------------------------------------------------------------------------------- 1 | 2 |

Welcome to section "item-1-1"

3 |
4 | -------------------------------------------------------------------------------- /demo/views/item-1-2.html: -------------------------------------------------------------------------------- 1 | 2 |

Welcome to section "item-1-2"

3 |
4 | -------------------------------------------------------------------------------- /demo/views/item-2.html: -------------------------------------------------------------------------------- 1 | 2 |

Welcome to section "item-2"

3 |
4 | -------------------------------------------------------------------------------- /demo/views/item-3-1.html: -------------------------------------------------------------------------------- 1 | 2 |

Welcome to section "item-3-1"

3 |
4 | -------------------------------------------------------------------------------- /demo/views/item-3-2-1.html: -------------------------------------------------------------------------------- 1 | 2 |

Welcome to section "item-3-2-1"

3 |
4 | -------------------------------------------------------------------------------- /demo/views/item-3-2-2-1.html: -------------------------------------------------------------------------------- 1 | 2 |

Welcome to section "item-3-2-2-1"

3 |
4 | -------------------------------------------------------------------------------- /demo/views/item-4-1.html: -------------------------------------------------------------------------------- 1 | 2 |

Welcome to section "item-4-1"

3 |
4 | -------------------------------------------------------------------------------- /demo/views/item-4-2.html: -------------------------------------------------------------------------------- 1 | 2 |

Welcome to section "item-4-2"

3 |
4 | -------------------------------------------------------------------------------- /demo/views/item-4.html: -------------------------------------------------------------------------------- 1 | 2 |

Welcome to section "item-4"

3 |
4 | -------------------------------------------------------------------------------- /demo/views/readme.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular-material-multilevel-menu", 3 | "version": "1.5.2", 4 | "description": "Material Multi-Level Menu for AngularJS", 5 | "main": "angular-material-multilevel-menu.js", 6 | "repository": "https://github.com/jmouriz/angular-material-multilevel-menu", 7 | "author": "Juan Manuel ", 8 | "license": "MIT", 9 | "dependencies": { 10 | "angular": "^1.6.5", 11 | "angular-animate": "^1.6.5", 12 | "angular-aria": "^1.6.5", 13 | "angular-material": "^1.1.4", 14 | "angular-material-icons": "^0.7.1", 15 | "jquery": "^3.2.1" 16 | }, 17 | "devDependencies": { 18 | "angular-marked": "^1.2.2", 19 | "angular-route": "^1.6.6", 20 | "minify": "^3.0.1", 21 | "prismjs": "^1.6.0" 22 | }, 23 | "optionalDependencies": { 24 | "angular-material-badge": "^1.2.2", 25 | "svg-morpheus": "^0.3.0" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /source/Makefile: -------------------------------------------------------------------------------- 1 | PACKAGE := $(shell grep name ../package.json | head -1 | cut -d: -f2 | tr -d '" ,') 2 | BUILD := ../build 3 | SOURCE := $(PACKAGE) 4 | TARGET := $(BUILD)/$(PACKAGE).min 5 | 6 | all: $(TARGET).js $(TARGET).css $(TARGET).html 7 | 8 | $(TARGET).css: $(SOURCE).css 9 | @../node_modules/.bin/minify $< > $@ 10 | 11 | $(TARGET).html: $(SOURCE).html 12 | @../node_modules/.bin/minify $< > $@ 13 | 14 | $(TARGET).js: $(SOURCE).js 15 | @../node_modules/.bin/minify $< > $@ 16 | -------------------------------------------------------------------------------- /source/angular-material-multilevel-menu.css: -------------------------------------------------------------------------------- 1 | .menu-container { 2 | height: 100%; 3 | display: flex; 4 | flex-direction: column; 5 | } 6 | 7 | .menu { 8 | position: relative; 9 | width: 100%; 10 | min-height: 100%; 11 | left: 0; 12 | clip-path: inset(0 0 0 0); 13 | } 14 | 15 | .menu.ng-animate { 16 | transition: all cubic-bezier(.25, .46, .45, .95) .35s; 17 | } 18 | 19 | .menu.left { 20 | left: -100%; 21 | clip-path: inset(0 0 0 100%); 22 | } 23 | 24 | .menu.right { 25 | left: 100%; 26 | clip-path: inset(0 100% 0 0); 27 | } 28 | 29 | .submenu { 30 | margin-left: 16px; 31 | } 32 | 33 | .submenu.slide { 34 | position: relative; 35 | overflow: hidden; 36 | } 37 | 38 | .submenu.slide.ng-enter { 39 | animation: 1.35s down; 40 | } 41 | 42 | .submenu.slide.ng-leave { 43 | animation: .35s up; 44 | } 45 | 46 | @keyframes down { 47 | from { 48 | max-height: 0; 49 | } 50 | to { 51 | max-height: 100vh; 52 | } 53 | } 54 | 55 | @keyframes up { 56 | from { 57 | max-height: 100vh; 58 | } 59 | to { 60 | max-height: 0; 61 | } 62 | } 63 | 64 | a.breadcrumb, 65 | a.breadcrumb:visited { 66 | color: inherit; 67 | text-decoration: none; 68 | } 69 | 70 | md-list.body { 71 | padding-top: 0; 72 | padding-bottom: 0; 73 | } 74 | -------------------------------------------------------------------------------- /source/angular-material-multilevel-menu.html: -------------------------------------------------------------------------------- 1 |