├── .editorconfig ├── .gitattributes ├── .gitignore ├── .jshintrc ├── Gruntfile.coffee ├── LICENSE ├── README.md ├── bower.json ├── dist ├── angular-hamburger-toggle.css ├── angular-hamburger-toggle.js ├── angular-hamburger-toggle.min.css └── angular-hamburger-toggle.min.js ├── index.html ├── package.json ├── src ├── scripts │ ├── app.coffee │ └── directives │ │ └── hamburgertoggle.coffee ├── styles │ ├── main.css │ └── material-design-hamburger.css └── views │ └── hamburger-toggle.html └── test ├── karma.conf.coffee └── spec └── directives └── hamburgertoggle.coffee /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain consistent 2 | # coding styles between different editors and IDEs 3 | # editorconfig.org 4 | 5 | root = true 6 | 7 | [*] 8 | end_of_line = lf 9 | charset = utf-8 10 | trim_trailing_whitespace = true 11 | insert_final_newline = false 12 | indent_style = space 13 | indent_size = 2 14 | 15 | [*.md] 16 | trim_trailing_whitespace = false -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .tmp 3 | .sass-cache 4 | bower_components 5 | docs 6 | coverage -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "node": true, 3 | "browser": true, 4 | "esnext": true, 5 | "bitwise": true, 6 | "camelcase": true, 7 | "curly": true, 8 | "eqeqeq": true, 9 | "immed": true, 10 | "indent": 2, 11 | "latedef": true, 12 | "newcap": true, 13 | "noarg": true, 14 | "quotmark": "single", 15 | "regexp": true, 16 | "undef": true, 17 | "unused": true, 18 | "strict": true, 19 | "trailing": true, 20 | "smarttabs": true, 21 | "globals": { 22 | "angular": false 23 | } 24 | } -------------------------------------------------------------------------------- /Gruntfile.coffee: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | module.exports = (grunt) -> 4 | loadGruntTasks = require 'load-grunt-tasks' 5 | timeGrunt = require 'time-grunt' 6 | 7 | loadGruntTasks grunt 8 | timeGrunt grunt 9 | 10 | # Run grunt config 11 | grunt.initConfig 12 | pkg: grunt.file.readJSON 'bower.json' 13 | appConfig: 14 | app: 'src' 15 | module: 'ngHamburger' 16 | test: 'app/test' 17 | name: 'Angular Hamburger Toggle' 18 | dist: 'dist' 19 | 20 | banner: '/*!\n' + 21 | ' * <%= pkg.name %> - v<%= pkg.version %>\n' + 22 | ' * <%= pkg.homepage %>\n' + 23 | ' * <%= grunt.template.today("yyyy-mm-dd") %>\n' + 24 | ' * İsmail Demirbilek\n' + 25 | ' * MIT License\n' + 26 | ' */\n' 27 | 28 | copy: 29 | app: 30 | expand: true 31 | cwd: '<%= appConfig.app %>' 32 | src: ['scripts/{,*/}*.js', 'styles/{,*/}*.css'] 33 | dest: '.tmp' 34 | dist: 35 | files: [ 36 | { 37 | expand: true 38 | dot: true 39 | cwd: "<%= appConfig.app %>" 40 | dest: "<%= appConfig.dist %>" 41 | src: [ 42 | "*.{ico,png,txt}" 43 | ".htaccess" 44 | "fonts/{,*/}*.*" 45 | ] 46 | } 47 | ] 48 | 49 | coffee: 50 | app: 51 | expand: true 52 | cwd: '<%= appConfig.app %>' 53 | src: ['scripts/{,*/}*.coffee'] 54 | dest: '.tmp' 55 | ext: '.js' 56 | 57 | ngtemplates: 58 | app: 59 | cwd: '<%= appConfig.app %>' 60 | src: 'views/{,*/}{,*/}*.html' 61 | dest: '.tmp/scripts/templates.js' 62 | options: 63 | module: '<%= appConfig.module %>' 64 | htmlmin: 65 | collapseWhitespace: true 66 | collapseBooleanAttributes: true 67 | 68 | wiredep: 69 | test: 70 | src: ['<%= karma.unit.configFile %>'] 71 | options: 72 | fileTypes: 73 | js: 74 | block: /(([\s\t]*)\/\/\s*bower:*(\S*))(\n|\r|.)*?(\/\/\s*endbower)/gi 75 | detect: 76 | js: /'(.*\.js)'/gi 77 | replace: 78 | js: '\'{{filePath}}\',' 79 | ignorePath: '../../' 80 | devDependencies: true 81 | exclude: ['jQuery', 'egemswatch'] 82 | 83 | concat: 84 | js: 85 | options: 86 | banner: '<%= banner %>\n' 87 | files: 88 | '<%= appConfig.dist %>/<%= pkg.name %>.js': ['.tmp/scripts/{,*/}{,*/}*.js'] 89 | css: 90 | options: 91 | banner: '<%= banner %>\n' 92 | files: 93 | '<%= appConfig.dist %>/<%= pkg.name %>.css': ['.tmp/styles/{,*/}{,*/}*.css'] 94 | 95 | cssmin: 96 | dist: 97 | files: 98 | '<%= appConfig.dist %>/<%= pkg.name %>.min.css': [ 99 | '<%= appConfig.dist %>/<%= pkg.name %>.css' 100 | ] 101 | 102 | connect: 103 | test: 104 | options: 105 | port: 9001 106 | base: [ 107 | '.tmp' 108 | 'test' 109 | '<%= appConfig.app %>' 110 | ] 111 | 112 | clean: 113 | dist: 114 | dot: true 115 | src: [ 116 | '.tmp' 117 | '<%= appConfig.dist %>/<%= pkg.name %>.{js,css}' 118 | '!<%= appConfig.dist %>/.git*' 119 | ] 120 | server: '.tmp' 121 | bower: 'static/bower_components' 122 | 123 | autoprefixer: 124 | options: 125 | browsers: ['last 1 version'] 126 | server: 127 | options: 128 | map: true 129 | files: [{ 130 | expand: true 131 | cwd: '.tmp/styles/' 132 | src: '{,*/}*.css' 133 | dest: '.tmp/styles/' 134 | }] 135 | dist: 136 | files: [{ 137 | expand: true 138 | cwd: '.tmp/styles/' 139 | src: '{,*/}*.css' 140 | dest: '.tmp/styles/' 141 | }] 142 | 143 | jshint: 144 | options: 145 | jshintrc: '.jshintrc' 146 | all: [ 147 | 'teest/spec/karma.conf.coffee' 148 | '<%= appConfig.app %>/{,*/}{,*/}{,*/}*.js' 149 | ] 150 | 151 | coffeelint: 152 | app: ['<%= appConfig.app %>/{,*/}**.coffee'] 153 | options: 154 | 'max_line_length': 155 | level: 'warn' 156 | 157 | karma: 158 | unit: 159 | configFile: 'test/karma.conf.coffee' 160 | singleRun: true 161 | 162 | ngAnnotate: 163 | dist: 164 | files: [ 165 | expand: true, 166 | cwd: '.tmp/scripts' 167 | src: '{,*/}{,*/}*.js' 168 | dest: '.tmp/scripts' 169 | ] 170 | 171 | uglify: 172 | dist: 173 | options: 174 | enclose: true 175 | banner: '<%= banner %>' 176 | files: 177 | '<%= appConfig.dist %>/<%= pkg.name %>.min.js': ['<%= appConfig.dist %>/<%= pkg.name %>.js'] 178 | 179 | ngdocs: 180 | options: 181 | dest: 'docs' 182 | html5Mode: false 183 | title: '<%= appConfig.name %> Documentation' 184 | all: ['.tmp/scripts/{,*/}{,*/}*.js'] 185 | 186 | grunt.registerTask 'test', [ 187 | 'clean:server', 188 | 'connect:test', 189 | 'karma' 190 | ] 191 | 192 | grunt.registerTask 'build', [ 193 | 'clean:dist' 194 | 'coffee' 195 | 'copy' 196 | 'ngtemplates' 197 | 'autoprefixer' 198 | 'concat:css' 199 | 'ngtemplates' 200 | 'ngAnnotate' 201 | 'concat:js' 202 | 'uglify' 203 | 'cssmin' 204 | ] 205 | 206 | grunt.registerTask 'default', [ 207 | 'jshint' 208 | 'coffeelint' 209 | 'wiredep' 210 | 'test' 211 | 'build' 212 | 'ngdocs' 213 | 'clean:server' 214 | ] 215 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 İsmail Demirbilek 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Angular Hamburger Toggle 2 | ------------------------ 3 | 4 | Angular directive of Material Design morphing hamburger menu toggle. It's based off of [Material Design Hamburger](https://github.com/swirlycheetah/material-design-hamburger). 5 | 6 | ![toggle-gif](https://i.imgur.com/B0PT1Lb.gif) 7 | 8 | ###Features 9 | * Two way bound state model. 10 | * Tuned for Bootstrap. 11 | * Super easy. 12 | 13 | ###[Demo](http://dbtek.github.io/angular-hamburger-toggle) 14 | 15 | ##Install 16 | ```bash 17 | $ bower install angular-hamburger-toggle --save 18 | ``` 19 | 20 | ##Usage 21 | 22 | * Add dependency 23 | ```js 24 | angular.module('myApp', ['ngHamburger']); 25 | ``` 26 | * Use directive 27 | ```html 28 | 29 | ``` 30 | 31 | `state` attribute is for two way bound model that will be toggled. Initially can be `true`, `false` or `undefined`. 32 | 33 | ##Credits 34 | [Material Design Hamburger](https://github.com/swirlycheetah/material-design-hamburger) 35 | 36 | ##Author 37 | İsmail Demirbilek - [@dbtek](https://twitter.com/dbtek) 38 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular-hamburger-toggle", 3 | "homepage": "https://github.com/dbtek/angular-hamburger-toggle", 4 | "version": "0.2.0", 5 | "dependencies": { 6 | "angular": ">=1.2.0" 7 | }, 8 | "devDependencies": { 9 | "angular-mocks": ">=1.2.0" 10 | }, 11 | "appPath": "src", 12 | "moduleName": "angularHamburgerToggleApp", 13 | "authors": [ 14 | "İsmail Demirbilek " 15 | ], 16 | "description": "Material Design morphing hamburger menu toggle for Angular JS.", 17 | "main": [ 18 | "dist/angular-hamburger-toggle.css", 19 | "dist/angular-hamburger-toggle.js" 20 | ], 21 | "keywords": [ 22 | "angular", 23 | "morphing", 24 | "material", 25 | "design", 26 | "toggle" 27 | ], 28 | "license": "MIT", 29 | "ignore": [ 30 | "**/.*", 31 | "node_modules", 32 | "bower_components", 33 | "test", 34 | "tests", 35 | "src", 36 | "test", 37 | ".*", 38 | "Gruntfile.coffee", 39 | "README.md", 40 | "index.html", 41 | "package.json" 42 | ] 43 | } 44 | -------------------------------------------------------------------------------- /dist/angular-hamburger-toggle.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * angular-hamburger-toggle - v0.2.0 3 | * https://github.com/dbtek/angular-hamburger-toggle 4 | * 2015-04-20 5 | * İsmail Demirbilek 6 | * MIT License 7 | */ 8 | 9 | .material-design-hamburger { 10 | width: 120px; 11 | margin-left: -46px; 12 | } 13 | :not(.navbar) .material-design-hamburger { 14 | -webkit-transform: scale(0.27); 15 | transform: scale(0.27); 16 | } 17 | .navbar .material-design-hamburger { 18 | position: absolute; 19 | top: 11px; 20 | -webkit-transform: scale(0.22); 21 | transform: scale(0.22); 22 | } 23 | .navbar .material-design-hamburger__layer { 24 | background: #777; 25 | } 26 | 27 | .material-design-hamburger button { 28 | outline: none; 29 | } 30 | 31 | .material-design-hamburger .material-design-hamburger__icon { 32 | padding: 1rem 1rem; 33 | } 34 | 35 | /* xs screens */ 36 | @media (max-width: 767px) { 37 | .navbar .navbar-header .material-design-hamburger { 38 | left: 5px; 39 | } 40 | } 41 | /** 42 | * Material Design Hamburger 43 | * https://github.com/swirlycheetah/material-design-hamburger 44 | * License: MIT 45 | */ 46 | 47 | .material-design-hamburger button { 48 | display: block; 49 | border: none; 50 | background: none; 51 | } 52 | 53 | .material-design-hamburger__icon { 54 | padding: 3rem 1rem; 55 | cursor: pointer; 56 | } 57 | 58 | .material-design-hamburger__layer { 59 | display: block; 60 | width: 100px; 61 | height: 10px; 62 | background: #111; 63 | position: relative; 64 | -webkit-animation-duration: 300ms; 65 | animation-duration: 300ms; 66 | -webkit-animation-timing-function: ease-in-out; 67 | animation-timing-function: ease-in-out; 68 | } 69 | 70 | .material-design-hamburger__layer:before, .material-design-hamburger__layer:after { 71 | display: block; 72 | width: inherit; 73 | height: 10px; 74 | position: absolute; 75 | background: inherit; 76 | left: 0; 77 | content: ''; 78 | -webkit-animation-duration: 300ms; 79 | animation-duration: 300ms; 80 | -webkit-animation-timing-function: ease-in-out; 81 | animation-timing-function: ease-in-out; 82 | } 83 | 84 | .material-design-hamburger__layer:before { 85 | bottom: 200%; 86 | } 87 | 88 | .material-design-hamburger__layer:after { 89 | top: 200%; 90 | } 91 | 92 | .material-design-hamburger__icon--to-arrow { 93 | -webkit-animation-name: material-design-hamburger__icon--slide; 94 | animation-name: material-design-hamburger__icon--slide; 95 | -webkit-animation-fill-mode: forwards; 96 | animation-fill-mode: forwards; 97 | } 98 | 99 | .material-design-hamburger__icon--to-arrow:before { 100 | -webkit-animation-name: material-design-hamburger__icon--slide-before; 101 | animation-name: material-design-hamburger__icon--slide-before; 102 | -webkit-animation-fill-mode: forwards; 103 | animation-fill-mode: forwards; 104 | } 105 | 106 | .material-design-hamburger__icon--to-arrow:after { 107 | -webkit-animation-name: material-design-hamburger__icon--slide-after; 108 | animation-name: material-design-hamburger__icon--slide-after; 109 | -webkit-animation-fill-mode: forwards; 110 | animation-fill-mode: forwards; 111 | } 112 | 113 | .material-design-hamburger__icon--from-arrow { 114 | -webkit-animation-name: material-design-hamburger__icon--slide-from; 115 | animation-name: material-design-hamburger__icon--slide-from; 116 | } 117 | 118 | .material-design-hamburger__icon--from-arrow:before { 119 | -webkit-animation-name: material-design-hamburger__icon--slide-before-from; 120 | animation-name: material-design-hamburger__icon--slide-before-from; 121 | } 122 | 123 | .material-design-hamburger__icon--from-arrow:after { 124 | -webkit-animation-name: material-design-hamburger__icon--slide-after-from; 125 | animation-name: material-design-hamburger__icon--slide-after-from; 126 | } 127 | 128 | @-webkit-keyframes material-design-hamburger__icon--slide { 129 | 0% { 130 | } 131 | 100% { 132 | -webkit-transform: rotate(180deg); 133 | transform: rotate(180deg); 134 | } 135 | } 136 | 137 | @keyframes material-design-hamburger__icon--slide { 138 | 0% { 139 | } 140 | 100% { 141 | -webkit-transform: rotate(180deg); 142 | transform: rotate(180deg); 143 | } 144 | } 145 | 146 | @-webkit-keyframes material-design-hamburger__icon--slide-before { 147 | 0% { 148 | } 149 | 100% { 150 | -webkit-transform: rotate(45deg); 151 | transform: rotate(45deg); 152 | margin: 3% 37%; 153 | width: 75%; 154 | } 155 | } 156 | 157 | @keyframes material-design-hamburger__icon--slide-before { 158 | 0% { 159 | } 160 | 100% { 161 | -webkit-transform: rotate(45deg); 162 | transform: rotate(45deg); 163 | margin: 3% 37%; 164 | width: 75%; 165 | } 166 | } 167 | 168 | @-webkit-keyframes material-design-hamburger__icon--slide-after { 169 | 0% { 170 | } 171 | 100% { 172 | -webkit-transform: rotate(-45deg); 173 | transform: rotate(-45deg); 174 | margin: 3% 37%; 175 | width: 75%; 176 | } 177 | } 178 | 179 | @keyframes material-design-hamburger__icon--slide-after { 180 | 0% { 181 | } 182 | 100% { 183 | -webkit-transform: rotate(-45deg); 184 | transform: rotate(-45deg); 185 | margin: 3% 37%; 186 | width: 75%; 187 | } 188 | } 189 | 190 | @-webkit-keyframes material-design-hamburger__icon--slide-from { 191 | 0% { 192 | -webkit-transform: rotate(-180deg); 193 | transform: rotate(-180deg); 194 | } 195 | 100% { 196 | } 197 | } 198 | 199 | @keyframes material-design-hamburger__icon--slide-from { 200 | 0% { 201 | -webkit-transform: rotate(-180deg); 202 | transform: rotate(-180deg); 203 | } 204 | 100% { 205 | } 206 | } 207 | 208 | @-webkit-keyframes material-design-hamburger__icon--slide-before-from { 209 | 0% { 210 | -webkit-transform: rotate(45deg); 211 | transform: rotate(45deg); 212 | margin: 3% 37%; 213 | width: 75%; 214 | } 215 | 100% { 216 | } 217 | } 218 | 219 | @keyframes material-design-hamburger__icon--slide-before-from { 220 | 0% { 221 | -webkit-transform: rotate(45deg); 222 | transform: rotate(45deg); 223 | margin: 3% 37%; 224 | width: 75%; 225 | } 226 | 100% { 227 | } 228 | } 229 | 230 | @-webkit-keyframes material-design-hamburger__icon--slide-after-from { 231 | 0% { 232 | -webkit-transform: rotate(-45deg); 233 | transform: rotate(-45deg); 234 | margin: 3% 37%; 235 | width: 75%; 236 | } 237 | 100% { 238 | } 239 | } 240 | 241 | @keyframes material-design-hamburger__icon--slide-after-from { 242 | 0% { 243 | -webkit-transform: rotate(-45deg); 244 | transform: rotate(-45deg); 245 | margin: 3% 37%; 246 | width: 75%; 247 | } 248 | 100% { 249 | } 250 | } -------------------------------------------------------------------------------- /dist/angular-hamburger-toggle.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * angular-hamburger-toggle - v0.2.0 3 | * https://github.com/dbtek/angular-hamburger-toggle 4 | * 2015-04-20 5 | * İsmail Demirbilek 6 | * MIT License 7 | */ 8 | 9 | (function() { 10 | 'use strict'; 11 | 12 | /** 13 | * @ngdoc overview 14 | * @name ngHamburger 15 | * @description 16 | * # ngHamburger 17 | * Main module of the application. 18 | */ 19 | angular.module('ngHamburger', []); 20 | 21 | }).call(this); 22 | 23 | (function() { 24 | 'use strict'; 25 | 26 | /** 27 | * @ngdoc directive 28 | * @name ngHamburger.directive:hamburgerToggle 29 | * @param {object} state - State model with two way binding. 30 | * @description 31 | * Morphing hamburger toggle directive. 32 | */ 33 | angular.module('ngHamburger').directive('hamburgerToggle', function() { 34 | return { 35 | restrict: 'E', 36 | replace: true, 37 | scope: { 38 | state: '=' 39 | }, 40 | templateUrl: 'views/hamburger-toggle.html', 41 | link: function($scope, $element, $attrs) { 42 | 43 | /** 44 | * @ngdoc object 45 | * @name toggleState 46 | * @methodOf ngHamburger.directive:hamburgerToggle 47 | * @description Toggles two way bound model. 48 | */ 49 | $scope.toggleState = function() { 50 | return $scope.state = !$scope.state; 51 | }; 52 | } 53 | }; 54 | }); 55 | 56 | }).call(this); 57 | 58 | angular.module('ngHamburger').run(['$templateCache', function($templateCache) { 59 | 'use strict'; 60 | 61 | $templateCache.put('views/hamburger-toggle.html', 62 | "
" 63 | ); 64 | 65 | }]); 66 | -------------------------------------------------------------------------------- /dist/angular-hamburger-toggle.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * angular-hamburger-toggle - v0.2.0 3 | * https://github.com/dbtek/angular-hamburger-toggle 4 | * 2015-04-20 5 | * İsmail Demirbilek 6 | * MIT License 7 | */.material-design-hamburger{width:120px;margin-left:-46px}:not(.navbar) .material-design-hamburger{-webkit-transform:scale(0.27);transform:scale(0.27)}.navbar .material-design-hamburger{position:absolute;top:11px;-webkit-transform:scale(0.22);transform:scale(0.22)}.navbar .material-design-hamburger__layer{background:#777}.material-design-hamburger button{outline:0}.material-design-hamburger .material-design-hamburger__icon{padding:1rem}@media (max-width:767px){.navbar .navbar-header .material-design-hamburger{left:5px}}.material-design-hamburger button{display:block;border:none;background:0 0}.material-design-hamburger__icon{padding:3rem 1rem;cursor:pointer}.material-design-hamburger__layer{display:block;width:100px;height:10px;background:#111;position:relative;-webkit-animation-duration:300ms;animation-duration:300ms;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}.material-design-hamburger__layer:after,.material-design-hamburger__layer:before{display:block;width:inherit;height:10px;position:absolute;background:inherit;left:0;content:'';-webkit-animation-duration:300ms;animation-duration:300ms;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}.material-design-hamburger__layer:before{bottom:200%}.material-design-hamburger__layer:after{top:200%}.material-design-hamburger__icon--to-arrow{-webkit-animation-name:material-design-hamburger__icon--slide;animation-name:material-design-hamburger__icon--slide;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards}.material-design-hamburger__icon--to-arrow:before{-webkit-animation-name:material-design-hamburger__icon--slide-before;animation-name:material-design-hamburger__icon--slide-before;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards}.material-design-hamburger__icon--to-arrow:after{-webkit-animation-name:material-design-hamburger__icon--slide-after;animation-name:material-design-hamburger__icon--slide-after;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards}.material-design-hamburger__icon--from-arrow{-webkit-animation-name:material-design-hamburger__icon--slide-from;animation-name:material-design-hamburger__icon--slide-from}.material-design-hamburger__icon--from-arrow:before{-webkit-animation-name:material-design-hamburger__icon--slide-before-from;animation-name:material-design-hamburger__icon--slide-before-from}.material-design-hamburger__icon--from-arrow:after{-webkit-animation-name:material-design-hamburger__icon--slide-after-from;animation-name:material-design-hamburger__icon--slide-after-from}@-webkit-keyframes material-design-hamburger__icon--slide{100%{-webkit-transform:rotate(180deg);transform:rotate(180deg)}}@keyframes material-design-hamburger__icon--slide{100%{-webkit-transform:rotate(180deg);transform:rotate(180deg)}}@-webkit-keyframes material-design-hamburger__icon--slide-before{100%{-webkit-transform:rotate(45deg);transform:rotate(45deg);margin:3% 37%;width:75%}}@keyframes material-design-hamburger__icon--slide-before{100%{-webkit-transform:rotate(45deg);transform:rotate(45deg);margin:3% 37%;width:75%}}@-webkit-keyframes material-design-hamburger__icon--slide-after{100%{-webkit-transform:rotate(-45deg);transform:rotate(-45deg);margin:3% 37%;width:75%}}@keyframes material-design-hamburger__icon--slide-after{100%{-webkit-transform:rotate(-45deg);transform:rotate(-45deg);margin:3% 37%;width:75%}}@-webkit-keyframes material-design-hamburger__icon--slide-from{0%{-webkit-transform:rotate(-180deg);transform:rotate(-180deg)}}@keyframes material-design-hamburger__icon--slide-from{0%{-webkit-transform:rotate(-180deg);transform:rotate(-180deg)}}@-webkit-keyframes material-design-hamburger__icon--slide-before-from{0%{-webkit-transform:rotate(45deg);transform:rotate(45deg);margin:3% 37%;width:75%}}@keyframes material-design-hamburger__icon--slide-before-from{0%{-webkit-transform:rotate(45deg);transform:rotate(45deg);margin:3% 37%;width:75%}}@-webkit-keyframes material-design-hamburger__icon--slide-after-from{0%{-webkit-transform:rotate(-45deg);transform:rotate(-45deg);margin:3% 37%;width:75%}}@keyframes material-design-hamburger__icon--slide-after-from{0%{-webkit-transform:rotate(-45deg);transform:rotate(-45deg);margin:3% 37%;width:75%}} -------------------------------------------------------------------------------- /dist/angular-hamburger-toggle.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * angular-hamburger-toggle - v0.2.0 3 | * https://github.com/dbtek/angular-hamburger-toggle 4 | * 2015-04-20 5 | * İsmail Demirbilek 6 | * MIT License 7 | */ 8 | !function(){(function(){"use strict";angular.module("ngHamburger",[])}).call(this),function(){"use strict";angular.module("ngHamburger").directive("hamburgerToggle",function(){return{restrict:"E",replace:!0,scope:{state:"="},templateUrl:"views/hamburger-toggle.html",link:function(a,b,c){a.toggleState=function(){return a.state=!a.state}}}})}.call(this),angular.module("ngHamburger").run(["$templateCache",function(a){"use strict";a.put("views/hamburger-toggle.html",'
')}])}(); -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Angular Hamburger Toggle 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 76 | 77 | 80 | 81 | 82 |
83 | 93 |
94 | 95 |
96 | 101 |
102 | 103 |
104 |
105 |

Demo

106 | 110 |

111 | Demo of Material Design morphing hamburger menu toggle for Angular JS. 112 |

113 | 121 | 122 |

Two Way Binding

123 |

Click toggle to see model change.

124 | $scope.tgState: {{tgState}} 125 |

126 | 127 |

128 | 129 |

Install

130 |
$ bower install angular-hamburger-toggle
131 | 132 |

Usage

133 |
angular.module('myApp', ['ngHamburger']);
134 |
<hamburger-toggle state="tgState"></hamburger-toggle>
135 | 136 | 137 |
138 |
139 | 140 | 147 | 148 |
149 | 150 | 151 | 152 | 158 | 167 | 168 | 171 | 172 | 173 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular-hamburger-toggle", 3 | "version": "0.2.0", 4 | "dependencies": {}, 5 | "repository": {}, 6 | "devDependencies": { 7 | "coffeelint": "^1.8.1", 8 | "grunt": "~0.4.4", 9 | "grunt-angular-templates": "^0.5.7", 10 | "grunt-autoprefixer": "^3.0.0", 11 | "grunt-coffeelint": "0.0.13", 12 | "grunt-contrib-clean": "~0.5.0", 13 | "grunt-contrib-coffee": "^0.11.1", 14 | "grunt-contrib-concat": "^0.5.0", 15 | "grunt-contrib-connect": "~0.5.0", 16 | "grunt-contrib-copy": "^0.7.0", 17 | "grunt-contrib-cssmin": "~0.9.0", 18 | "grunt-contrib-htmlmin": "^0.3.0", 19 | "grunt-contrib-jshint": "~0.9.2", 20 | "grunt-contrib-uglify": "~0.4.0", 21 | "grunt-folder-list": "^1.1.0", 22 | "grunt-karma": "~0.8.2", 23 | "grunt-ng-annotate": "^0.4.0", 24 | "grunt-ngdocs": "~0.2.2", 25 | "grunt-usemin": "~2.1.0", 26 | "grunt-wiredep": "^1.9.0", 27 | "karma": "~0.12.1", 28 | "karma-coffee-preprocessor": "^0.2.1", 29 | "karma-coverage": "~0.2.4", 30 | "karma-html2js-preprocessor": "~0.1.0", 31 | "karma-jasmine": "~0.2.2", 32 | "karma-phantomjs-launcher": "~0.1.2", 33 | "karma-requirejs": "~0.2.1", 34 | "karma-script-launcher": "~0.1.0", 35 | "karma-spec-reporter": "~0.0.13", 36 | "load-grunt-tasks": "~0.4.0", 37 | "time-grunt": "~0.2.7" 38 | }, 39 | "engines": { 40 | "node": ">=0.10.0" 41 | }, 42 | "scripts": { 43 | "test": "grunt test" 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/scripts/app.coffee: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | ###* 4 | # @ngdoc overview 5 | # @name ngHamburger 6 | # @description 7 | # # ngHamburger 8 | # Main module of the application. 9 | ### 10 | angular.module 'ngHamburger', [] 11 | -------------------------------------------------------------------------------- /src/scripts/directives/hamburgertoggle.coffee: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | ###* 4 | # @ngdoc directive 5 | # @name ngHamburger.directive:hamburgerToggle 6 | # @param {object} state - State model with two way binding. 7 | # @description 8 | # Morphing hamburger toggle directive. 9 | ### 10 | angular.module 'ngHamburger' 11 | .directive 'hamburgerToggle', -> 12 | restrict: 'E' 13 | replace: true 14 | scope: 15 | state: '=' 16 | templateUrl: 'views/hamburger-toggle.html' 17 | link: ($scope, $element, $attrs) -> 18 | 19 | ###* 20 | # @ngdoc object 21 | # @name toggleState 22 | # @methodOf ngHamburger.directive:hamburgerToggle 23 | # @description Toggles two way bound model. 24 | ### 25 | $scope.toggleState = -> 26 | $scope.state = !$scope.state 27 | 28 | return -------------------------------------------------------------------------------- /src/styles/main.css: -------------------------------------------------------------------------------- 1 | .material-design-hamburger { 2 | width: 120px; 3 | margin-left: -46px; 4 | } 5 | :not(.navbar) .material-design-hamburger { 6 | transform: scale(0.27); 7 | } 8 | .navbar .material-design-hamburger { 9 | position: absolute; 10 | top: 11px; 11 | transform: scale(0.22); 12 | } 13 | .navbar .material-design-hamburger__layer { 14 | background: #777; 15 | } 16 | 17 | .material-design-hamburger button { 18 | outline: none; 19 | } 20 | 21 | .material-design-hamburger .material-design-hamburger__icon { 22 | padding: 1rem 1rem; 23 | } 24 | 25 | /* xs screens */ 26 | @media (max-width: 767px) { 27 | .navbar .navbar-header .material-design-hamburger { 28 | left: 5px; 29 | } 30 | } -------------------------------------------------------------------------------- /src/styles/material-design-hamburger.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Material Design Hamburger 3 | * https://github.com/swirlycheetah/material-design-hamburger 4 | * License: MIT 5 | */ 6 | 7 | .material-design-hamburger button { 8 | display: block; 9 | border: none; 10 | background: none; 11 | } 12 | 13 | .material-design-hamburger__icon { 14 | padding: 3rem 1rem; 15 | cursor: pointer; 16 | } 17 | 18 | .material-design-hamburger__layer { 19 | display: block; 20 | width: 100px; 21 | height: 10px; 22 | background: #111; 23 | position: relative; 24 | -webkit-animation-duration: 300ms; 25 | animation-duration: 300ms; 26 | -webkit-animation-timing-function: ease-in-out; 27 | animation-timing-function: ease-in-out; 28 | } 29 | 30 | .material-design-hamburger__layer:before, .material-design-hamburger__layer:after { 31 | display: block; 32 | width: inherit; 33 | height: 10px; 34 | position: absolute; 35 | background: inherit; 36 | left: 0; 37 | content: ''; 38 | -webkit-animation-duration: 300ms; 39 | animation-duration: 300ms; 40 | -webkit-animation-timing-function: ease-in-out; 41 | animation-timing-function: ease-in-out; 42 | } 43 | 44 | .material-design-hamburger__layer:before { 45 | bottom: 200%; 46 | } 47 | 48 | .material-design-hamburger__layer:after { 49 | top: 200%; 50 | } 51 | 52 | .material-design-hamburger__icon--to-arrow { 53 | -webkit-animation-name: material-design-hamburger__icon--slide; 54 | animation-name: material-design-hamburger__icon--slide; 55 | -webkit-animation-fill-mode: forwards; 56 | animation-fill-mode: forwards; 57 | } 58 | 59 | .material-design-hamburger__icon--to-arrow:before { 60 | -webkit-animation-name: material-design-hamburger__icon--slide-before; 61 | animation-name: material-design-hamburger__icon--slide-before; 62 | -webkit-animation-fill-mode: forwards; 63 | animation-fill-mode: forwards; 64 | } 65 | 66 | .material-design-hamburger__icon--to-arrow:after { 67 | -webkit-animation-name: material-design-hamburger__icon--slide-after; 68 | animation-name: material-design-hamburger__icon--slide-after; 69 | -webkit-animation-fill-mode: forwards; 70 | animation-fill-mode: forwards; 71 | } 72 | 73 | .material-design-hamburger__icon--from-arrow { 74 | -webkit-animation-name: material-design-hamburger__icon--slide-from; 75 | animation-name: material-design-hamburger__icon--slide-from; 76 | } 77 | 78 | .material-design-hamburger__icon--from-arrow:before { 79 | -webkit-animation-name: material-design-hamburger__icon--slide-before-from; 80 | animation-name: material-design-hamburger__icon--slide-before-from; 81 | } 82 | 83 | .material-design-hamburger__icon--from-arrow:after { 84 | -webkit-animation-name: material-design-hamburger__icon--slide-after-from; 85 | animation-name: material-design-hamburger__icon--slide-after-from; 86 | } 87 | 88 | @-webkit-keyframes material-design-hamburger__icon--slide { 89 | 0% { 90 | } 91 | 100% { 92 | -webkit-transform: rotate(180deg); 93 | transform: rotate(180deg); 94 | } 95 | } 96 | 97 | @keyframes material-design-hamburger__icon--slide { 98 | 0% { 99 | } 100 | 100% { 101 | -webkit-transform: rotate(180deg); 102 | transform: rotate(180deg); 103 | } 104 | } 105 | 106 | @-webkit-keyframes material-design-hamburger__icon--slide-before { 107 | 0% { 108 | } 109 | 100% { 110 | -webkit-transform: rotate(45deg); 111 | transform: rotate(45deg); 112 | margin: 3% 37%; 113 | width: 75%; 114 | } 115 | } 116 | 117 | @keyframes material-design-hamburger__icon--slide-before { 118 | 0% { 119 | } 120 | 100% { 121 | -webkit-transform: rotate(45deg); 122 | transform: rotate(45deg); 123 | margin: 3% 37%; 124 | width: 75%; 125 | } 126 | } 127 | 128 | @-webkit-keyframes material-design-hamburger__icon--slide-after { 129 | 0% { 130 | } 131 | 100% { 132 | -webkit-transform: rotate(-45deg); 133 | transform: rotate(-45deg); 134 | margin: 3% 37%; 135 | width: 75%; 136 | } 137 | } 138 | 139 | @keyframes material-design-hamburger__icon--slide-after { 140 | 0% { 141 | } 142 | 100% { 143 | -webkit-transform: rotate(-45deg); 144 | transform: rotate(-45deg); 145 | margin: 3% 37%; 146 | width: 75%; 147 | } 148 | } 149 | 150 | @-webkit-keyframes material-design-hamburger__icon--slide-from { 151 | 0% { 152 | -webkit-transform: rotate(-180deg); 153 | transform: rotate(-180deg); 154 | } 155 | 100% { 156 | } 157 | } 158 | 159 | @keyframes material-design-hamburger__icon--slide-from { 160 | 0% { 161 | -webkit-transform: rotate(-180deg); 162 | transform: rotate(-180deg); 163 | } 164 | 100% { 165 | } 166 | } 167 | 168 | @-webkit-keyframes material-design-hamburger__icon--slide-before-from { 169 | 0% { 170 | -webkit-transform: rotate(45deg); 171 | transform: rotate(45deg); 172 | margin: 3% 37%; 173 | width: 75%; 174 | } 175 | 100% { 176 | } 177 | } 178 | 179 | @keyframes material-design-hamburger__icon--slide-before-from { 180 | 0% { 181 | -webkit-transform: rotate(45deg); 182 | transform: rotate(45deg); 183 | margin: 3% 37%; 184 | width: 75%; 185 | } 186 | 100% { 187 | } 188 | } 189 | 190 | @-webkit-keyframes material-design-hamburger__icon--slide-after-from { 191 | 0% { 192 | -webkit-transform: rotate(-45deg); 193 | transform: rotate(-45deg); 194 | margin: 3% 37%; 195 | width: 75%; 196 | } 197 | 100% { 198 | } 199 | } 200 | 201 | @keyframes material-design-hamburger__icon--slide-after-from { 202 | 0% { 203 | -webkit-transform: rotate(-45deg); 204 | transform: rotate(-45deg); 205 | margin: 3% 37%; 206 | width: 75%; 207 | } 208 | 100% { 209 | } 210 | } -------------------------------------------------------------------------------- /src/views/hamburger-toggle.html: -------------------------------------------------------------------------------- 1 |
2 | 7 |
8 | -------------------------------------------------------------------------------- /test/karma.conf.coffee: -------------------------------------------------------------------------------- 1 | # Karma configuration 2 | # http://karma-runner.github.io/0.12/config/configuration-file.html 3 | # Generated on 2015-04-03 using 4 | # generator-karma 0.9.0 5 | 6 | module.exports = (config) -> 7 | config.set 8 | # base path, that will be used to resolve files and exclude 9 | basePath: '../' 10 | 11 | # testing framework to use (jasmine/mocha/qunit/...) 12 | frameworks: ['jasmine'] 13 | 14 | # list of files / patterns to load in the browser 15 | files: [ 16 | # bower:js 17 | 'bower_components/angular/angular.js' 18 | 'bower_components/angular-mocks/angular-mocks.js' 19 | # endbower 20 | # bower:coffee 21 | # endbower 22 | 'src/scripts/**/*.coffee' 23 | 'test/mock/**/*.coffee' 24 | 'test/spec/**/*.coffee' 25 | ], 26 | 27 | # list of files / patterns to exclude 28 | exclude: [ 29 | ] 30 | 31 | # web server port 32 | port: 8080 33 | 34 | # level of logging 35 | # possible values: LOG_DISABLE || LOG_ERROR || LOG_WARN || LOG_INFO || LOG_DEBUG 36 | logLevel: config.LOG_INFO 37 | 38 | # Start these browsers, currently available: 39 | # - Chrome 40 | # - ChromeCanary 41 | # - Firefox 42 | # - Opera 43 | # - Safari (only Mac) 44 | # - PhantomJS 45 | # - IE (only Windows) 46 | browsers: [ 47 | 'PhantomJS' 48 | ] 49 | 50 | # Which plugins to enable 51 | plugins: [ 52 | 'karma-phantomjs-launcher', 53 | 'karma-jasmine', 54 | 'karma-coffee-preprocessor' 55 | ] 56 | 57 | # enable / disable watching file and executing tests whenever any file changes 58 | autoWatch: true 59 | 60 | # Continuous Integration mode 61 | # if true, it capture browsers, run tests and exit 62 | singleRun: false 63 | 64 | colors: true 65 | 66 | preprocessors: '**/*.coffee': ['coffee'] 67 | 68 | # Uncomment the following lines if you are using grunt's server to run the tests 69 | # proxies: '/': 'http://localhost:9000/' 70 | # URL root prevent conflicts with the site root 71 | # urlRoot: '_karma_' 72 | -------------------------------------------------------------------------------- /test/spec/directives/hamburgertoggle.coffee: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | describe 'Directive: hamburgerToggle', -> 4 | 5 | # load the directive's module 6 | beforeEach module 'ngHamburger' 7 | 8 | scope = {} 9 | 10 | beforeEach inject ($controller, $rootScope) -> 11 | scope = $rootScope.$new() 12 | 13 | it 'should make hidden element visible', inject ($compile) -> 14 | element = angular.element '' 15 | element = $compile(element) scope 16 | expect(!!element).toBe true 17 | --------------------------------------------------------------------------------