├── .bowerrc ├── .editorconfig ├── .gitattributes ├── .gitignore ├── .jshintrc ├── .travis.yml ├── Gruntfile.js ├── LICENSE ├── README.md ├── app ├── .buildignore ├── .htaccess ├── 404.html ├── favicon.ico ├── images │ └── .gitkeep ├── index.html ├── robots.txt ├── scripts │ ├── app.js │ └── controllers │ │ ├── nav.js │ │ └── profile-pic.js ├── styles │ ├── main.scss │ └── profile-pic.css └── views │ ├── footer.jade │ ├── main.jade │ ├── nav.jade │ └── profile-pic.jade ├── bower.json ├── config.js ├── karma-e2e.conf.js ├── karma.conf.js ├── package.json ├── runner ├── server-runner.js ├── server.js └── test ├── .jshintrc ├── runner.html └── spec └── controllers ├── nav.js └── profile-pic.js /.bowerrc: -------------------------------------------------------------------------------- 1 | { 2 | "directory": "app/bower_components" 3 | } 4 | -------------------------------------------------------------------------------- /.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 | [*] 9 | 10 | # Change these settings to your own preference 11 | indent_style = space 12 | indent_size = 2 13 | 14 | # We recommend you to keep these unchanged 15 | end_of_line = lf 16 | charset = utf-8 17 | trim_trailing_whitespace = true 18 | insert_final_newline = true 19 | 20 | [*.md] 21 | trim_trailing_whitespace = false 22 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | .tmp 3 | .sass-cache 4 | app/bower_components 5 | app/angular-ui-bootstrap 6 | app/views/*.html 7 | priv/ 8 | 9 | lib-cov 10 | *.seed 11 | *.log 12 | *.csv 13 | *.dat 14 | *.out 15 | *.pid 16 | *.gz 17 | 18 | pids 19 | logs 20 | results 21 | 22 | npm-debug.log 23 | node_modules 24 | -------------------------------------------------------------------------------- /.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 | "laxcomma": true, 15 | "laxbreak": true, 16 | "regexp": true, 17 | "undef": true, 18 | "unused": true, 19 | "strict": true, 20 | "trailing": true, 21 | "smarttabs": true, 22 | "globals": { 23 | "angular": false 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - '0.8' 4 | - '0.10' 5 | before_script: 6 | - 'npm install -g bower grunt-cli' 7 | - 'bower install' 8 | -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | // Generated on 2013-12-02 using generator-angular 0.6.0-rc.2 2 | 'use strict'; 3 | 4 | var server = require('./server') 5 | , config = require('./config') 6 | , port = config.port 7 | , lrPort = 37926 8 | , lrSnippet = require('connect-livereload')({ port: lrPort }) 9 | ; 10 | 11 | // # Globbing 12 | // for performance reasons we're only matching one level down: 13 | // 'test/spec/{,*/}*.js' 14 | // use this if you want to recursively match all subfolders: 15 | // 'test/spec/**/*.js' 16 | 17 | module.exports = function (grunt) { 18 | 19 | // Load grunt tasks automatically 20 | require('load-grunt-tasks')(grunt); 21 | 22 | // Time how long tasks take. Can help when optimizing build times 23 | require('time-grunt')(grunt); 24 | 25 | // Define the configuration for all the tasks 26 | grunt.initConfig({ 27 | 28 | // Project settings 29 | yeoman: { 30 | // configurable paths 31 | app: require('./bower.json').appPath || 'app', 32 | dist: 'dist' 33 | }, 34 | 35 | // Watches files for changes and runs tasks based on the changed files 36 | watch: { 37 | js: { 38 | files: ['{.tmp,<%= yeoman.app %>}/scripts/{,*/}*.js'], 39 | tasks: ['newer:jshint:all'] 40 | }, 41 | jsTest: { 42 | files: ['test/spec/{,*/}*.js'], 43 | tasks: ['newer:jshint:test', 'karma'] 44 | }, 45 | compass: { 46 | files: ['<%= yeoman.app %>/styles/{,*/}*.{scss,sass}'], 47 | tasks: ['compass:server', 'autoprefixer'] 48 | }, 49 | styles: { 50 | files: ['<%= yeoman.app %>/styles/{,*/}*.css'], 51 | tasks: ['newer:copy:styles', 'autoprefixer'] 52 | }, 53 | gruntfile: { 54 | files: ['Gruntfile.js'] 55 | }, 56 | jade: { 57 | files: ['<%= yeoman.app %>/{,*/}*.jade'], 58 | tasks: ['jade'] 59 | }, 60 | livereload: { 61 | options: { 62 | livereload: '<%= connect.options.livereload %>' 63 | }, 64 | files: [ 65 | '{<%= yeoman.app %>,.tmp}/{,*/}*.html', 66 | '.tmp/styles/{,*/}*.css', 67 | '<%= yeoman.app %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}' 68 | ] 69 | } 70 | }, 71 | 72 | // The actual grunt server settings 73 | connect: { 74 | options: { 75 | port: port 76 | // Change this to '0.0.0.0' to access the server from outside. 77 | , hostname: 'localhost' 78 | , livereload: lrPort 79 | }, 80 | livereload: { 81 | options: { 82 | open: config.href 83 | , base: [ 84 | '.tmp', 85 | '<%= yeoman.app %>' 86 | ] 87 | , middleware: function (/*connect*/) { 88 | return [ 89 | 90 | lrSnippet 91 | , server 92 | ]; 93 | } 94 | } 95 | }, 96 | test: { 97 | options: { 98 | port: port, 99 | base: [ 100 | '.tmp', 101 | 'test', 102 | '<%= yeoman.app %>' 103 | ], 104 | middleware: function (/*connect*/) { 105 | return [ 106 | server 107 | ]; 108 | } 109 | } 110 | }, 111 | dist: { 112 | options: { 113 | base: '<%= yeoman.dist %>', 114 | middleware: function (/*connect*/) { 115 | return [ 116 | server 117 | ]; 118 | } 119 | } 120 | } 121 | }, 122 | 123 | // Make sure code styles are up to par and there are no obvious mistakes 124 | jshint: { 125 | options: { 126 | jshintrc: '.jshintrc', 127 | reporter: require('jshint-stylish') 128 | }, 129 | all: [ 130 | 'Gruntfile.js', 131 | '<%= yeoman.app %>/scripts/{,*/}*.js' 132 | ], 133 | test: { 134 | options: { 135 | jshintrc: 'test/.jshintrc' 136 | }, 137 | src: ['test/spec/{,*/}*.js'] 138 | } 139 | }, 140 | 141 | // Empties folders to start fresh 142 | clean: { 143 | dist: { 144 | files: [{ 145 | dot: true, 146 | src: [ 147 | '.tmp', 148 | '<%= yeoman.dist %>/*', 149 | '!<%= yeoman.dist %>/.git*' 150 | ] 151 | }] 152 | }, 153 | server: '.tmp' 154 | }, 155 | 156 | // Allow Jade 157 | jade: { 158 | dist: { 159 | options: { 160 | pretty: true 161 | }, 162 | files: [{ 163 | expand: true, 164 | cwd: '<%= yeoman.app %>', 165 | dest: '.tmp', 166 | src: '{,*/}*.jade', 167 | ext: '.html' 168 | }] 169 | } 170 | }, 171 | 172 | // Add vendor prefixed styles 173 | autoprefixer: { 174 | options: { 175 | browsers: ['last 1 version'] 176 | }, 177 | dist: { 178 | files: [{ 179 | expand: true, 180 | cwd: '.tmp/styles/', 181 | src: '{,*/}*.css', 182 | dest: '.tmp/styles/' 183 | }] 184 | } 185 | }, 186 | 187 | 188 | 189 | 190 | // Compiles Sass to CSS and generates necessary files if requested 191 | compass: { 192 | options: { 193 | sassDir: '<%= yeoman.app %>/styles', 194 | cssDir: '.tmp/styles', 195 | generatedImagesDir: '.tmp/images/generated', 196 | imagesDir: '<%= yeoman.app %>/images', 197 | javascriptsDir: '<%= yeoman.app %>/scripts', 198 | fontsDir: '<%= yeoman.app %>/styles/fonts', 199 | importPath: '<%= yeoman.app %>/bower_components', 200 | httpImagesPath: '/images', 201 | httpGeneratedImagesPath: '/images/generated', 202 | httpFontsPath: '/styles/fonts', 203 | relativeAssets: false, 204 | assetCacheBuster: false 205 | }, 206 | dist: { 207 | options: { 208 | generatedImagesDir: '<%= yeoman.dist %>/images/generated' 209 | } 210 | }, 211 | server: { 212 | options: { 213 | debugInfo: true 214 | } 215 | } 216 | }, 217 | 218 | // Renames files for browser caching purposes 219 | rev: { 220 | dist: { 221 | files: { 222 | src: [ 223 | '<%= yeoman.dist %>/scripts/{,*/}*.js', 224 | '<%= yeoman.dist %>/styles/{,*/}*.css', 225 | '<%= yeoman.dist %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}', 226 | '<%= yeoman.dist %>/styles/fonts/*' 227 | ] 228 | } 229 | } 230 | }, 231 | 232 | // Reads HTML for usemin blocks to enable smart builds that automatically 233 | // concat, minify and revision files. Creates configurations in memory so 234 | // additional tasks can operate on them 235 | useminPrepare: { 236 | html: '<%= yeoman.app %>/index.html', 237 | options: { 238 | dest: '<%= yeoman.dist %>' 239 | } 240 | }, 241 | 242 | // Performs rewrites based on rev and the useminPrepare configuration 243 | usemin: { 244 | html: ['<%= yeoman.dist %>/{,*/}*.html'], 245 | css: ['<%= yeoman.dist %>/styles/{,*/}*.css'], 246 | options: { 247 | assetsDirs: ['<%= yeoman.dist %>'] 248 | } 249 | }, 250 | 251 | // The following *-min tasks produce minified files in the dist folder 252 | imagemin: { 253 | dist: { 254 | files: [{ 255 | expand: true, 256 | cwd: '<%= yeoman.app %>/images', 257 | src: '{,*/}*.{png,jpg,jpeg,gif}', 258 | dest: '<%= yeoman.dist %>/images' 259 | }] 260 | } 261 | }, 262 | svgmin: { 263 | dist: { 264 | files: [{ 265 | expand: true, 266 | cwd: '<%= yeoman.app %>/images', 267 | src: '{,*/}*.svg', 268 | dest: '<%= yeoman.dist %>/images' 269 | }] 270 | } 271 | }, 272 | htmlmin: { 273 | dist: { 274 | options: { 275 | // Optional configurations that you can uncomment to use 276 | // removeCommentsFromCDATA: true, 277 | // collapseBooleanAttributes: true, 278 | // removeAttributeQuotes: true, 279 | // removeRedundantAttributes: true, 280 | // useShortDoctype: true, 281 | // removeEmptyAttributes: true, 282 | // removeOptionalTags: true*/ 283 | }, 284 | files: [{ 285 | expand: true, 286 | cwd: '<%= yeoman.app %>', 287 | src: ['*.html', 'views/*.html'], 288 | dest: '<%= yeoman.dist %>' 289 | }] 290 | } 291 | }, 292 | 293 | // Allow the use of non-minsafe AngularJS files. Automatically makes it 294 | // minsafe compatible so Uglify does not destroy the ng references 295 | ngmin: { 296 | dist: { 297 | files: [{ 298 | expand: true, 299 | cwd: '.tmp/concat/scripts', 300 | src: '*.js', 301 | dest: '.tmp/concat/scripts' 302 | }] 303 | } 304 | }, 305 | 306 | // Replace Google CDN references 307 | cdnify: { 308 | dist: { 309 | html: ['<%= yeoman.dist %>/*.html'] 310 | } 311 | }, 312 | 313 | // Copies remaining files to places other tasks can use 314 | copy: { 315 | dist: { 316 | files: [{ 317 | expand: true, 318 | dot: true, 319 | cwd: '<%= yeoman.app %>', 320 | dest: '<%= yeoman.dist %>', 321 | src: [ 322 | '*.{ico,png,txt}', 323 | '.htaccess', 324 | 'bower_components/**/*', 325 | 'images/{,*/}*.{webp}', 326 | 'fonts/*' 327 | ] 328 | }, { 329 | expand: true, 330 | cwd: '.tmp/images', 331 | dest: '<%= yeoman.dist %>/images', 332 | src: [ 333 | 'generated/*' 334 | ] 335 | }, { 336 | expand: true, 337 | cwd: '.tmp/views', 338 | dest: '<%= yeoman.dist %>/views', 339 | src: [ 340 | '*.html' 341 | ] 342 | }] 343 | }, 344 | styles: { 345 | expand: true, 346 | cwd: '<%= yeoman.app %>/styles', 347 | dest: '.tmp/styles/', 348 | src: '{,*/}*.css' 349 | } 350 | }, 351 | 352 | // Run some tasks in parallel to speed up the build process 353 | concurrent: { 354 | server: [ 355 | 'jade', 356 | 'compass:server', 357 | 'copy:styles' 358 | ], 359 | test: [ 360 | 'jade', 361 | 'compass', 362 | 'copy:styles' 363 | ], 364 | dist: [ 365 | 'jade', 366 | 'compass:dist', 367 | 'copy:styles', 368 | 'imagemin', 369 | 'svgmin', 370 | 'htmlmin' 371 | ] 372 | }, 373 | 374 | // By default, your `index.html`'s will take care of 375 | // minification. These next options are pre-configured if you do not wish 376 | // to use the Usemin blocks. 377 | // cssmin: { 378 | // dist: { 379 | // files: { 380 | // '<%= yeoman.dist %>/styles/main.css': [ 381 | // '.tmp/styles/{,*/}*.css', 382 | // '<%= yeoman.app %>/styles/{,*/}*.css' 383 | // ] 384 | // } 385 | // } 386 | // }, 387 | // uglify: { 388 | // dist: { 389 | // files: { 390 | // '<%= yeoman.dist %>/scripts/scripts.js': [ 391 | // '<%= yeoman.dist %>/scripts/scripts.js' 392 | // ] 393 | // } 394 | // } 395 | // }, 396 | // concat: { 397 | // dist: {} 398 | // }, 399 | 400 | // Test settings 401 | karma: { 402 | unit: { 403 | configFile: 'karma.conf.js', 404 | singleRun: true 405 | } 406 | } 407 | }); 408 | 409 | 410 | grunt.registerTask('serve', function (target) { 411 | if (target === 'dist') { 412 | return grunt.task.run(['build', 'connect:dist:keepalive']); 413 | } 414 | 415 | grunt.task.run([ 416 | 'clean:server', 417 | 'concurrent:server', 418 | 'autoprefixer', 419 | 'connect:livereload', 420 | 'watch' 421 | ]); 422 | }); 423 | 424 | grunt.registerTask('server', function () { 425 | grunt.log.warn('The `server` task has been deprecated. Use `grunt serve` to start a server.'); 426 | grunt.task.run(['serve']); 427 | }); 428 | 429 | grunt.registerTask('test', [ 430 | 'clean:server', 431 | 'concurrent:test', 432 | 'autoprefixer', 433 | 'connect:test', 434 | 'karma' 435 | ]); 436 | 437 | grunt.registerTask('build', [ 438 | 'clean:dist', 439 | 'jade', 440 | 'useminPrepare', 441 | 'concurrent:dist', 442 | 'autoprefixer', 443 | 'concat', 444 | 'ngmin', 445 | 'copy:dist', 446 | 'cdnify', 447 | 'cssmin', 448 | 'uglify', 449 | 'rev', 450 | 'usemin' 451 | ]); 452 | 453 | grunt.registerTask('default', [ 454 | 'newer:jshint', 455 | 'test', 456 | 'build' 457 | ]); 458 | }; 459 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | 203 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Moved 2 | ### [angular-image-crop](https://git.daplie.com/coolaj86/angular-image-crop) is now at [git.daplie.com/coolaj86/angular-image-crop](https://git.daplie.com/coolaj86/angular-image-crop) 3 | -------------------------------------------------------------------------------- /app/.buildignore: -------------------------------------------------------------------------------- 1 | *.coffee -------------------------------------------------------------------------------- /app/.htaccess: -------------------------------------------------------------------------------- 1 | # Apache Configuration File 2 | 3 | # (!) Using `.htaccess` files slows down Apache, therefore, if you have access 4 | # to the main server config file (usually called `httpd.conf`), you should add 5 | # this logic there: http://httpd.apache.org/docs/current/howto/htaccess.html. 6 | 7 | # ############################################################################## 8 | # # CROSS-ORIGIN RESOURCE SHARING (CORS) # 9 | # ############################################################################## 10 | 11 | # ------------------------------------------------------------------------------ 12 | # | Cross-domain AJAX requests | 13 | # ------------------------------------------------------------------------------ 14 | 15 | # Enable cross-origin AJAX requests. 16 | # http://code.google.com/p/html5security/wiki/CrossOriginRequestSecurity 17 | # http://enable-cors.org/ 18 | 19 | # 20 | # Header set Access-Control-Allow-Origin "*" 21 | # 22 | 23 | # ------------------------------------------------------------------------------ 24 | # | CORS-enabled images | 25 | # ------------------------------------------------------------------------------ 26 | 27 | # Send the CORS header for images when browsers request it. 28 | # https://developer.mozilla.org/en/CORS_Enabled_Image 29 | # http://blog.chromium.org/2011/07/using-cross-domain-images-in-webgl-and.html 30 | # http://hacks.mozilla.org/2011/11/using-cors-to-load-webgl-textures-from-cross-domain-images/ 31 | 32 | 33 | 34 | 35 | SetEnvIf Origin ":" IS_CORS 36 | Header set Access-Control-Allow-Origin "*" env=IS_CORS 37 | 38 | 39 | 40 | 41 | # ------------------------------------------------------------------------------ 42 | # | Web fonts access | 43 | # ------------------------------------------------------------------------------ 44 | 45 | # Allow access from all domains for web fonts 46 | 47 | 48 | 49 | Header set Access-Control-Allow-Origin "*" 50 | 51 | 52 | 53 | 54 | # ############################################################################## 55 | # # ERRORS # 56 | # ############################################################################## 57 | 58 | # ------------------------------------------------------------------------------ 59 | # | 404 error prevention for non-existing redirected folders | 60 | # ------------------------------------------------------------------------------ 61 | 62 | # Prevent Apache from returning a 404 error for a rewrite if a directory 63 | # with the same name does not exist. 64 | # http://httpd.apache.org/docs/current/content-negotiation.html#multiviews 65 | # http://www.webmasterworld.com/apache/3808792.htm 66 | 67 | Options -MultiViews 68 | 69 | # ------------------------------------------------------------------------------ 70 | # | Custom error messages / pages | 71 | # ------------------------------------------------------------------------------ 72 | 73 | # You can customize what Apache returns to the client in case of an error (see 74 | # http://httpd.apache.org/docs/current/mod/core.html#errordocument), e.g.: 75 | 76 | ErrorDocument 404 /404.html 77 | 78 | 79 | # ############################################################################## 80 | # # INTERNET EXPLORER # 81 | # ############################################################################## 82 | 83 | # ------------------------------------------------------------------------------ 84 | # | Better website experience | 85 | # ------------------------------------------------------------------------------ 86 | 87 | # Force IE to render pages in the highest available mode in the various 88 | # cases when it may not: http://hsivonen.iki.fi/doctype/ie-mode.pdf. 89 | 90 | 91 | Header set X-UA-Compatible "IE=edge" 92 | # `mod_headers` can't match based on the content-type, however, we only 93 | # want to send this header for HTML pages and not for the other resources 94 | 95 | Header unset X-UA-Compatible 96 | 97 | 98 | 99 | # ------------------------------------------------------------------------------ 100 | # | Cookie setting from iframes | 101 | # ------------------------------------------------------------------------------ 102 | 103 | # Allow cookies to be set from iframes in IE. 104 | 105 | # 106 | # Header set P3P "policyref=\"/w3c/p3p.xml\", CP=\"IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT\"" 107 | # 108 | 109 | # ------------------------------------------------------------------------------ 110 | # | Screen flicker | 111 | # ------------------------------------------------------------------------------ 112 | 113 | # Stop screen flicker in IE on CSS rollovers (this only works in 114 | # combination with the `ExpiresByType` directives for images from below). 115 | 116 | # BrowserMatch "MSIE" brokenvary=1 117 | # BrowserMatch "Mozilla/4.[0-9]{2}" brokenvary=1 118 | # BrowserMatch "Opera" !brokenvary 119 | # SetEnvIf brokenvary 1 force-no-vary 120 | 121 | 122 | # ############################################################################## 123 | # # MIME TYPES AND ENCODING # 124 | # ############################################################################## 125 | 126 | # ------------------------------------------------------------------------------ 127 | # | Proper MIME types for all files | 128 | # ------------------------------------------------------------------------------ 129 | 130 | 131 | 132 | # Audio 133 | AddType audio/mp4 m4a f4a f4b 134 | AddType audio/ogg oga ogg 135 | 136 | # JavaScript 137 | # Normalize to standard type (it's sniffed in IE anyways): 138 | # http://tools.ietf.org/html/rfc4329#section-7.2 139 | AddType application/javascript js jsonp 140 | AddType application/json json 141 | 142 | # Video 143 | AddType video/mp4 mp4 m4v f4v f4p 144 | AddType video/ogg ogv 145 | AddType video/webm webm 146 | AddType video/x-flv flv 147 | 148 | # Web fonts 149 | AddType application/font-woff woff 150 | AddType application/vnd.ms-fontobject eot 151 | 152 | # Browsers usually ignore the font MIME types and sniff the content, 153 | # however, Chrome shows a warning if other MIME types are used for the 154 | # following fonts. 155 | AddType application/x-font-ttf ttc ttf 156 | AddType font/opentype otf 157 | 158 | # Make SVGZ fonts work on iPad: 159 | # https://twitter.com/FontSquirrel/status/14855840545 160 | AddType image/svg+xml svg svgz 161 | AddEncoding gzip svgz 162 | 163 | # Other 164 | AddType application/octet-stream safariextz 165 | AddType application/x-chrome-extension crx 166 | AddType application/x-opera-extension oex 167 | AddType application/x-shockwave-flash swf 168 | AddType application/x-web-app-manifest+json webapp 169 | AddType application/x-xpinstall xpi 170 | AddType application/xml atom rdf rss xml 171 | AddType image/webp webp 172 | AddType image/x-icon ico 173 | AddType text/cache-manifest appcache manifest 174 | AddType text/vtt vtt 175 | AddType text/x-component htc 176 | AddType text/x-vcard vcf 177 | 178 | 179 | 180 | # ------------------------------------------------------------------------------ 181 | # | UTF-8 encoding | 182 | # ------------------------------------------------------------------------------ 183 | 184 | # Use UTF-8 encoding for anything served as `text/html` or `text/plain`. 185 | AddDefaultCharset utf-8 186 | 187 | # Force UTF-8 for certain file formats. 188 | 189 | AddCharset utf-8 .atom .css .js .json .rss .vtt .webapp .xml 190 | 191 | 192 | 193 | # ############################################################################## 194 | # # URL REWRITES # 195 | # ############################################################################## 196 | 197 | # ------------------------------------------------------------------------------ 198 | # | Rewrite engine | 199 | # ------------------------------------------------------------------------------ 200 | 201 | # Turning on the rewrite engine and enabling the `FollowSymLinks` option is 202 | # necessary for the following directives to work. 203 | 204 | # If your web host doesn't allow the `FollowSymlinks` option, you may need to 205 | # comment it out and use `Options +SymLinksIfOwnerMatch` but, be aware of the 206 | # performance impact: http://httpd.apache.org/docs/current/misc/perf-tuning.html#symlinks 207 | 208 | # Also, some cloud hosting services require `RewriteBase` to be set: 209 | # http://www.rackspace.com/knowledge_center/frequently-asked-question/why-is-mod-rewrite-not-working-on-my-site 210 | 211 | 212 | Options +FollowSymlinks 213 | # Options +SymLinksIfOwnerMatch 214 | RewriteEngine On 215 | # RewriteBase / 216 | 217 | 218 | # ------------------------------------------------------------------------------ 219 | # | Suppressing / Forcing the "www." at the beginning of URLs | 220 | # ------------------------------------------------------------------------------ 221 | 222 | # The same content should never be available under two different URLs especially 223 | # not with and without "www." at the beginning. This can cause SEO problems 224 | # (duplicate content), therefore, you should choose one of the alternatives and 225 | # redirect the other one. 226 | 227 | # By default option 1 (no "www.") is activated: 228 | # http://no-www.org/faq.php?q=class_b 229 | 230 | # If you'd prefer to use option 2, just comment out all the lines from option 1 231 | # and uncomment the ones from option 2. 232 | 233 | # IMPORTANT: NEVER USE BOTH RULES AT THE SAME TIME! 234 | 235 | # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 236 | 237 | # Option 1: rewrite www.example.com → example.com 238 | 239 | 240 | RewriteCond %{HTTPS} !=on 241 | RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC] 242 | RewriteRule ^ http://%1%{REQUEST_URI} [R=301,L] 243 | 244 | 245 | # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 246 | 247 | # Option 2: rewrite example.com → www.example.com 248 | 249 | # Be aware that the following might not be a good idea if you use "real" 250 | # subdomains for certain parts of your website. 251 | 252 | # 253 | # RewriteCond %{HTTPS} !=on 254 | # RewriteCond %{HTTP_HOST} !^www\..+$ [NC] 255 | # RewriteRule ^ http://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L] 256 | # 257 | 258 | 259 | # ############################################################################## 260 | # # SECURITY # 261 | # ############################################################################## 262 | 263 | # ------------------------------------------------------------------------------ 264 | # | Content Security Policy (CSP) | 265 | # ------------------------------------------------------------------------------ 266 | 267 | # You can mitigate the risk of cross-site scripting and other content-injection 268 | # attacks by setting a Content Security Policy which whitelists trusted sources 269 | # of content for your site. 270 | 271 | # The example header below allows ONLY scripts that are loaded from the current 272 | # site's origin (no inline scripts, no CDN, etc). This almost certainly won't 273 | # work as-is for your site! 274 | 275 | # To get all the details you'll need to craft a reasonable policy for your site, 276 | # read: http://html5rocks.com/en/tutorials/security/content-security-policy (or 277 | # see the specification: http://w3.org/TR/CSP). 278 | 279 | # 280 | # Header set Content-Security-Policy "script-src 'self'; object-src 'self'" 281 | # 282 | # Header unset Content-Security-Policy 283 | # 284 | # 285 | 286 | # ------------------------------------------------------------------------------ 287 | # | File access | 288 | # ------------------------------------------------------------------------------ 289 | 290 | # Block access to directories without a default document. 291 | # Usually you should leave this uncommented because you shouldn't allow anyone 292 | # to surf through every directory on your server (which may includes rather 293 | # private places like the CMS's directories). 294 | 295 | 296 | Options -Indexes 297 | 298 | 299 | # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 300 | 301 | # Block access to hidden files and directories. 302 | # This includes directories used by version control systems such as Git and SVN. 303 | 304 | 305 | RewriteCond %{SCRIPT_FILENAME} -d [OR] 306 | RewriteCond %{SCRIPT_FILENAME} -f 307 | RewriteRule "(^|/)\." - [F] 308 | 309 | 310 | # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 311 | 312 | # Block access to backup and source files. 313 | # These files may be left by some text editors and can pose a great security 314 | # danger when anyone has access to them. 315 | 316 | 317 | Order allow,deny 318 | Deny from all 319 | Satisfy All 320 | 321 | 322 | # ------------------------------------------------------------------------------ 323 | # | Secure Sockets Layer (SSL) | 324 | # ------------------------------------------------------------------------------ 325 | 326 | # Rewrite secure requests properly to prevent SSL certificate warnings, e.g.: 327 | # prevent `https://www.example.com` when your certificate only allows 328 | # `https://secure.example.com`. 329 | 330 | # 331 | # RewriteCond %{SERVER_PORT} !^443 332 | # RewriteRule ^ https://example-domain-please-change-me.com%{REQUEST_URI} [R=301,L] 333 | # 334 | 335 | # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 336 | 337 | # Force client-side SSL redirection. 338 | 339 | # If a user types "example.com" in his browser, the above rule will redirect him 340 | # to the secure version of the site. That still leaves a window of opportunity 341 | # (the initial HTTP connection) for an attacker to downgrade or redirect the 342 | # request. The following header ensures that browser will ONLY connect to your 343 | # server via HTTPS, regardless of what the users type in the address bar. 344 | # http://www.html5rocks.com/en/tutorials/security/transport-layer-security/ 345 | 346 | # 347 | # Header set Strict-Transport-Security max-age=16070400; 348 | # 349 | 350 | # ------------------------------------------------------------------------------ 351 | # | Server software information | 352 | # ------------------------------------------------------------------------------ 353 | 354 | # Avoid displaying the exact Apache version number, the description of the 355 | # generic OS-type and the information about Apache's compiled-in modules. 356 | 357 | # ADD THIS DIRECTIVE IN THE `httpd.conf` AS IT WILL NOT WORK IN THE `.htaccess`! 358 | 359 | # ServerTokens Prod 360 | 361 | 362 | # ############################################################################## 363 | # # WEB PERFORMANCE # 364 | # ############################################################################## 365 | 366 | # ------------------------------------------------------------------------------ 367 | # | Compression | 368 | # ------------------------------------------------------------------------------ 369 | 370 | 371 | 372 | # Force compression for mangled headers. 373 | # http://developer.yahoo.com/blogs/ydn/posts/2010/12/pushing-beyond-gzipping 374 | 375 | 376 | SetEnvIfNoCase ^(Accept-EncodXng|X-cept-Encoding|X{15}|~{15}|-{15})$ ^((gzip|deflate)\s*,?\s*)+|[X~-]{4,13}$ HAVE_Accept-Encoding 377 | RequestHeader append Accept-Encoding "gzip,deflate" env=HAVE_Accept-Encoding 378 | 379 | 380 | 381 | # Compress all output labeled with one of the following MIME-types 382 | # (for Apache versions below 2.3.7, you don't need to enable `mod_filter` 383 | # and can remove the `` and `` lines 384 | # as `AddOutputFilterByType` is still in the core directives). 385 | 386 | AddOutputFilterByType DEFLATE application/atom+xml \ 387 | application/javascript \ 388 | application/json \ 389 | application/rss+xml \ 390 | application/vnd.ms-fontobject \ 391 | application/x-font-ttf \ 392 | application/x-web-app-manifest+json \ 393 | application/xhtml+xml \ 394 | application/xml \ 395 | font/opentype \ 396 | image/svg+xml \ 397 | image/x-icon \ 398 | text/css \ 399 | text/html \ 400 | text/plain \ 401 | text/x-component \ 402 | text/xml 403 | 404 | 405 | 406 | 407 | # ------------------------------------------------------------------------------ 408 | # | Content transformations | 409 | # ------------------------------------------------------------------------------ 410 | 411 | # Prevent some of the mobile network providers from modifying the content of 412 | # your site: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.5. 413 | 414 | # 415 | # Header set Cache-Control "no-transform" 416 | # 417 | 418 | # ------------------------------------------------------------------------------ 419 | # | ETag removal | 420 | # ------------------------------------------------------------------------------ 421 | 422 | # Since we're sending far-future expires headers (see below), ETags can 423 | # be removed: http://developer.yahoo.com/performance/rules.html#etags. 424 | 425 | # `FileETag None` is not enough for every server. 426 | 427 | Header unset ETag 428 | 429 | 430 | FileETag None 431 | 432 | # ------------------------------------------------------------------------------ 433 | # | Expires headers (for better cache control) | 434 | # ------------------------------------------------------------------------------ 435 | 436 | # The following expires headers are set pretty far in the future. If you don't 437 | # control versioning with filename-based cache busting, consider lowering the 438 | # cache time for resources like CSS and JS to something like 1 week. 439 | 440 | 441 | 442 | ExpiresActive on 443 | ExpiresDefault "access plus 1 month" 444 | 445 | # CSS 446 | ExpiresByType text/css "access plus 1 year" 447 | 448 | # Data interchange 449 | ExpiresByType application/json "access plus 0 seconds" 450 | ExpiresByType application/xml "access plus 0 seconds" 451 | ExpiresByType text/xml "access plus 0 seconds" 452 | 453 | # Favicon (cannot be renamed!) 454 | ExpiresByType image/x-icon "access plus 1 week" 455 | 456 | # HTML components (HTCs) 457 | ExpiresByType text/x-component "access plus 1 month" 458 | 459 | # HTML 460 | ExpiresByType text/html "access plus 0 seconds" 461 | 462 | # JavaScript 463 | ExpiresByType application/javascript "access plus 1 year" 464 | 465 | # Manifest files 466 | ExpiresByType application/x-web-app-manifest+json "access plus 0 seconds" 467 | ExpiresByType text/cache-manifest "access plus 0 seconds" 468 | 469 | # Media 470 | ExpiresByType audio/ogg "access plus 1 month" 471 | ExpiresByType image/gif "access plus 1 month" 472 | ExpiresByType image/jpeg "access plus 1 month" 473 | ExpiresByType image/png "access plus 1 month" 474 | ExpiresByType video/mp4 "access plus 1 month" 475 | ExpiresByType video/ogg "access plus 1 month" 476 | ExpiresByType video/webm "access plus 1 month" 477 | 478 | # Web feeds 479 | ExpiresByType application/atom+xml "access plus 1 hour" 480 | ExpiresByType application/rss+xml "access plus 1 hour" 481 | 482 | # Web fonts 483 | ExpiresByType application/font-woff "access plus 1 month" 484 | ExpiresByType application/vnd.ms-fontobject "access plus 1 month" 485 | ExpiresByType application/x-font-ttf "access plus 1 month" 486 | ExpiresByType font/opentype "access plus 1 month" 487 | ExpiresByType image/svg+xml "access plus 1 month" 488 | 489 | 490 | 491 | # ------------------------------------------------------------------------------ 492 | # | Filename-based cache busting | 493 | # ------------------------------------------------------------------------------ 494 | 495 | # If you're not using a build process to manage your filename version revving, 496 | # you might want to consider enabling the following directives to route all 497 | # requests such as `/css/style.12345.css` to `/css/style.css`. 498 | 499 | # To understand why this is important and a better idea than `*.css?v231`, read: 500 | # http://stevesouders.com/blog/2008/08/23/revving-filenames-dont-use-querystring 501 | 502 | # 503 | # RewriteCond %{REQUEST_FILENAME} !-f 504 | # RewriteCond %{REQUEST_FILENAME} !-d 505 | # RewriteRule ^(.+)\.(\d+)\.(js|css|png|jpg|gif)$ $1.$3 [L] 506 | # 507 | 508 | # ------------------------------------------------------------------------------ 509 | # | File concatenation | 510 | # ------------------------------------------------------------------------------ 511 | 512 | # Allow concatenation from within specific CSS and JS files, e.g.: 513 | # Inside of `script.combined.js` you could have 514 | # 515 | # 516 | # and they would be included into this single file. 517 | 518 | # 519 | # 520 | # Options +Includes 521 | # AddOutputFilterByType INCLUDES application/javascript application/json 522 | # SetOutputFilter INCLUDES 523 | # 524 | # 525 | # Options +Includes 526 | # AddOutputFilterByType INCLUDES text/css 527 | # SetOutputFilter INCLUDES 528 | # 529 | # 530 | 531 | # ------------------------------------------------------------------------------ 532 | # | Persistent connections | 533 | # ------------------------------------------------------------------------------ 534 | 535 | # Allow multiple requests to be sent over the same TCP connection: 536 | # http://httpd.apache.org/docs/current/en/mod/core.html#keepalive. 537 | 538 | # Enable if you serve a lot of static content but, be aware of the 539 | # possible disadvantages! 540 | 541 | # 542 | # Header set Connection Keep-Alive 543 | # 544 | -------------------------------------------------------------------------------- /app/404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Page Not Found :( 6 | 141 | 142 | 143 |
144 |

Not found :(

145 |

Sorry, but the page you were trying to view does not exist.

146 |

It looks like this was the result of either:

147 | 151 | 154 | 155 |
156 | 157 | 158 | -------------------------------------------------------------------------------- /app/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coolaj86/angular-image-crop/978ddd5873d017fbd7ff11995d5dd18cc009acf7/app/favicon.ico -------------------------------------------------------------------------------- /app/images/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coolaj86/angular-image-crop/978ddd5873d017fbd7ff11995d5dd18cc009acf7/app/images/.gitkeep -------------------------------------------------------------------------------- /app/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Angular Image Crop 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 30 | 31 | 35 | 36 | 37 | 38 |
39 | 40 | 41 | 42 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /app/robots.txt: -------------------------------------------------------------------------------- 1 | # robotstxt.org 2 | 3 | User-agent: * 4 | -------------------------------------------------------------------------------- /app/scripts/app.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('profilepicApp', [ 4 | 'ngCookies', 5 | 'ngResource', 6 | 'ngSanitize', 7 | 'ui.router', 8 | 'ui.bootstrap', 9 | 'aj.crop' 10 | ]) 11 | .config(function ($stateProvider, $urlRouterProvider) { 12 | var nav 13 | , footer 14 | ; 15 | 16 | // IMPORTANT: (Issue #4) 17 | // These funny arrays (in resolve) are neccessary because ui.router 18 | // doesn't get properly mangled by ng-min 19 | // See https://github.com/yeoman/generator-angular#minification-safe 20 | nav = { 21 | templateUrl: 'views/nav.html' 22 | , controller: 'NavCtrl as N' 23 | }; 24 | 25 | footer = { 26 | templateUrl: 'views/footer.html' 27 | }; 28 | 29 | //$locationProvider.html5Mode(true); 30 | 31 | // Deal with missing trailing slash 32 | $urlRouterProvider.rule(function($injector, $location) { 33 | var path = $location.path(), search = $location.search() 34 | ; 35 | 36 | if (path[path.length - 1] === '/') { 37 | return; 38 | } 39 | 40 | if (Object.keys(search).length === 0) { 41 | return path + '/'; 42 | } 43 | 44 | var params = [] 45 | ; 46 | 47 | angular.forEach(search, function(v, k){ 48 | params.push(k + '=' + v); 49 | }); 50 | 51 | return path + '/?' + params.join('&'); 52 | }); 53 | $urlRouterProvider.otherwise('/profile-pic/'); 54 | 55 | $stateProvider 56 | .state('profile-pic', { 57 | url: '/profile-pic/' 58 | , views: { 59 | nav: nav 60 | , body: { 61 | templateUrl: 'views/profile-pic.html' 62 | , controller: 'ProfilePicCtrl as P' 63 | } 64 | , footer: footer 65 | } 66 | }) 67 | ; 68 | }); 69 | -------------------------------------------------------------------------------- /app/scripts/controllers/nav.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('profilepicApp') 4 | .controller('NavCtrl', function ($state) { 5 | var allTabs 6 | ; 7 | 8 | allTabs = [ 9 | { active: $state.includes('root') 10 | , title: 'Home' 11 | , href: $state.href('root') 12 | } 13 | , { active: $state.includes('profile-pic') 14 | , title: 'Profile' 15 | , href: $state.href('profile-pic') 16 | } 17 | ]; 18 | }); 19 | -------------------------------------------------------------------------------- /app/scripts/controllers/profile-pic.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('aj.crop', []) 4 | .directive('imgCropped', function($window) { 5 | var bounds = {} 6 | ; 7 | 8 | return { 9 | restrict: 'E', 10 | replace: true, 11 | scope: { src:'=', selected:'&' }, 12 | //link: function (scope, element, attr) { 13 | link: function (scope, element) { 14 | var myImg 15 | , clear = function() { 16 | if (myImg) { 17 | myImg.next().remove(); 18 | myImg.remove(); 19 | myImg = undefined; 20 | } 21 | } 22 | ; 23 | 24 | scope.$watch('src', function (nv) { 25 | clear(); 26 | 27 | console.log('[src]'); 28 | console.log(nv); 29 | if (!nv) { // newValue 30 | return; 31 | } 32 | 33 | element.after(''); 34 | myImg = element.next(); 35 | myImg.attr('src', nv); 36 | $window.jQuery(myImg).Jcrop( 37 | { trackDocument: true 38 | , onSelect: function(cords) { 39 | scope.$apply(function() { 40 | cords.bx = bounds.x; 41 | cords.by = bounds.y; 42 | scope.selected({cords: cords}); 43 | }); 44 | } 45 | , aspectRatio: 1.333333333333333333 46 | } 47 | , function () { 48 | // Use the API to get the real image size 49 | var boundsArr = this.getBounds(); 50 | bounds.x = boundsArr[0]; 51 | bounds.y = boundsArr[1]; 52 | } 53 | ); 54 | }); 55 | 56 | scope.$on('$destroy', clear); 57 | } 58 | }; 59 | }); 60 | 61 | // TODO create proper module 62 | angular.module('profilepicApp') 63 | .factory("fileReader", function ($q) { 64 | var onLoad = function (reader, deferred, Sscope) { 65 | return function () { 66 | Sscope.$apply(function () { 67 | deferred.resolve(reader.result); 68 | }); 69 | }; 70 | }; 71 | var onError = function (reader, deferred, Sscope) { 72 | return function () { 73 | Sscope.$apply(function () { 74 | deferred.reject(reader.result); 75 | }); 76 | }; 77 | }; 78 | var onProgress = function (reader, Sscope) { 79 | return function (event) { 80 | Sscope.$broadcast( 81 | "fileProgress" 82 | , { total: event.total 83 | , loaded: event.loaded 84 | } 85 | ); 86 | }; 87 | }; 88 | var getReader = function (deferred, Sscope) { 89 | var reader = new FileReader(); 90 | reader.onload = onLoad(reader, deferred, Sscope); 91 | reader.onerror = onError(reader, deferred, Sscope); 92 | reader.onprogress = onProgress(reader, Sscope); 93 | return reader; 94 | }; 95 | var readAsDataURL = function (file, Sscope) { 96 | var deferred = $q.defer(); 97 | var reader = getReader(deferred, Sscope); 98 | reader.readAsDataURL(file); 99 | return deferred.promise; 100 | }; 101 | return { readAsDataUrl: readAsDataURL }; 102 | }); 103 | 104 | angular.module('profilepicApp').directive("ajFileSelect", function () { 105 | return { 106 | scope: { 107 | "ajChange": "&ajChange" 108 | , "ajModel": "=ajModel" 109 | } 110 | , link: function(dirScope, el) { 111 | el.bind("change", function(e) { 112 | dirScope.ajModel.file = (e.srcElement || e.target).files[0]; 113 | console.log('ajFileSelect about to call getFile()', dirScope.ajModel); 114 | dirScope.ajChange(); 115 | }); 116 | } 117 | }; 118 | }); 119 | 120 | angular.module('profilepicApp') 121 | .controller('ProfilePicCtrl', function ($window, $timeout, $scope, fileReader) { 122 | var scope = this 123 | ; 124 | 125 | console.log(fileReader); 126 | 127 | scope.file = {}; 128 | scope.getFile = function () { 129 | console.log('getFile() called.'); 130 | console.log(scope.ajModel); 131 | console.log(scope.file); 132 | $scope.progress = 0; 133 | fileReader.readAsDataUrl(scope.file.file, $scope).then(function (result) { 134 | console.log('readAsDataUrl: result.length === ', result.length); 135 | //console.log(result); 136 | scope.imageSrc = result; 137 | $scope.imageSrc = result; 138 | $timeout(function () { 139 | scope.initJcrop(); 140 | }); 141 | }); 142 | }; 143 | 144 | $scope.$on("fileProgress", function(e, progress) { 145 | $scope.progress = progress.loaded / progress.total; 146 | }); 147 | 148 | scope.initJcrop = function () { 149 | console.log('init jcrop'); 150 | $window.jQuery('img.aj-crop').Jcrop({ 151 | onSelect: function () { 152 | //$scope.$apply(); 153 | console.log('onSelect', arguments); 154 | } 155 | , onChange: function () { 156 | //$scope.$apply(); 157 | console.log('onChange', arguments); 158 | } 159 | , trackDocument: true 160 | , aspectRatio: 1.333333333333333333 161 | }); 162 | }; 163 | 164 | // http://plnkr.co/edit/Iizykd7UORy3po1h5mfm?p=preview 165 | scope.cropOpts = { 166 | ratioW: 1 167 | , ratioH: 1 168 | }; 169 | $scope.selected = function (cords) { 170 | var scale 171 | ; 172 | 173 | scope.picWidth = cords.w; 174 | scope.picHeight = cords.h; 175 | 176 | console.log('scale'); 177 | if (scope.picWidth > 400) { 178 | scale = (400 / scope.picWidth); 179 | console.log(scope.picHeight); 180 | scope.picHeight *= scale; 181 | scope.picWidth *= scale; 182 | console.log(scale); 183 | } 184 | 185 | if (scope.picHeight > 400) { 186 | scale = (400 / scope.picHeight); 187 | scope.picHeight *= scale; 188 | scope.picWidth *= scale; 189 | console.log(scale); 190 | } 191 | 192 | console.log('[cords]', scope.picWidth / scope.picHeight); 193 | console.log(cords); 194 | $scope.cropped = true; 195 | 196 | var rx = scope.picWidth / cords.w 197 | , ry = scope.picHeight / cords.h 198 | , canvas = document.createElement("canvas") 199 | , context = canvas.getContext('2d') 200 | , imageObj = $window.jQuery('img#preview')[0] 201 | ; 202 | 203 | 204 | $window.jQuery('.canvas-preview').children().remove(); 205 | canvas.width = cords.w; 206 | canvas.height = cords.h; 207 | context.drawImage(imageObj, cords.x, cords.y, cords.w, cords.h, 0, 0, cords.w, cords.h); 208 | $window.jQuery('.canvas-preview').append(canvas); 209 | 210 | 211 | $window.jQuery('img#preview').css({ 212 | width: Math.round(rx * cords.bx) + 'px', 213 | height: Math.round(ry * cords.by) + 'px', 214 | marginLeft: '-' + Math.round(rx * cords.x) + 'px', 215 | marginTop: '-' + Math.round(ry * cords.y) + 'px' 216 | }); 217 | }; 218 | }); 219 | -------------------------------------------------------------------------------- /app/styles/main.scss: -------------------------------------------------------------------------------- 1 | .browsehappy { 2 | margin: 0.2em 0; 3 | background: #ccc; 4 | color: #000; 5 | padding: 0.2em 0; 6 | } 7 | 8 | /* Space out content a bit */ 9 | body { 10 | padding-top: 20px; 11 | padding-bottom: 20px; 12 | } 13 | 14 | /* Everything but the jumbotron gets side spacing for mobile first views */ 15 | .header, 16 | .marketing, 17 | .footer { 18 | padding-left: 15px; 19 | padding-right: 15px; 20 | } 21 | 22 | /* Custom page header */ 23 | .header { 24 | border-bottom: 1px solid #e5e5e5; 25 | } 26 | 27 | /* Make the masthead heading the same height as the navigation */ 28 | .header h3 { 29 | margin-top: 0; 30 | margin-bottom: 0; 31 | line-height: 40px; 32 | padding-bottom: 19px; 33 | } 34 | 35 | /* Custom page footer */ 36 | .footer { 37 | padding-top: 19px; 38 | color: #777; 39 | border-top: 1px solid #e5e5e5; 40 | } 41 | 42 | .container-narrow > hr { 43 | margin: 30px 0; 44 | } 45 | 46 | /* Main marketing message and sign up button */ 47 | .jumbotron { 48 | text-align: center; 49 | border-bottom: 1px solid #e5e5e5; 50 | } 51 | 52 | .jumbotron .btn { 53 | font-size: 21px; 54 | padding: 14px 24px; 55 | } 56 | 57 | /* Supporting marketing content */ 58 | .marketing { 59 | margin: 40px 0; 60 | } 61 | 62 | .marketing p + h4 { 63 | margin-top: 28px; 64 | } 65 | 66 | /* Responsive: Portrait tablets and up */ 67 | @media screen and (min-width: 768px) { 68 | .container { 69 | max-width: 730px; 70 | } 71 | 72 | /* Remove the padding we set earlier */ 73 | .header, 74 | .marketing, 75 | .footer { 76 | padding-left: 0; 77 | padding-right: 0; 78 | } 79 | /* Space out the masthead */ 80 | .header { 81 | margin-bottom: 30px; 82 | } 83 | /* Remove the bottom border on the jumbotron for visual effect */ 84 | .jumbotron { 85 | border-bottom: 0; 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /app/styles/profile-pic.css: -------------------------------------------------------------------------------- 1 | div#cropped-image { 2 | height: 150px; 3 | width: 150px; 4 | overflow: hidden; 5 | } 6 | -------------------------------------------------------------------------------- /app/views/footer.jade: -------------------------------------------------------------------------------- 1 | .footer 2 | .container 3 | center 4 | span Built with 5 | a(target="_blank" 6 | , href="https://ldsconnect.org/vids/built-with-love" 7 | , style="text-decoration: none; color: #F778A1; font-size: 1.3em;" 8 | ) ♥ 9 | span by 10 | a(target="_blank", href="http://blog.coolaj86.com") AJ 11 | span ( 12 | a(target="_blank", href="http://AJ.the.DJ") the DJ 13 | span ) 14 | a(target="_blank", href="http://fb.com/coolaj86") ONeal 15 | -------------------------------------------------------------------------------- /app/views/main.jade: -------------------------------------------------------------------------------- 1 | .container 2 | .row 3 | .col-sm-12 4 | h2 You gotsta know your house! 5 | //-.jumbotron 6 | h1 'Allo, 'Allo! 7 | p.lead 8 | img(src='images/yeoman.png', alt='I"m Yeoman') 9 | br 10 | | Always a pleasure scaffolding your apps. 11 | p 12 | a.btn.btn-lg.btn-success(ng-href='#') Splendid! 13 | 14 | .row.marketing 15 | .col-sm-12 16 | div(ng-if="!M.current && !M.results") 17 | button.btn.btn-primary(ng-click="M.startQuiz()", type="button") Find Your House 18 | 19 | div(ng-if="M.current") 20 | span {{ M.current.total - M.current.remaining }} of {{ M.current.total }} 21 | strong Which suits you best? 22 | span 23 | | (# 24 | | {{ M.current.number }}) 25 | div 26 | p(ng-repeat="choice in M.current.choices") 27 | button.btn.btn-primary(ng-click="M.respond($index)", type="button") {{ $index + 1 }} 28 | span {{ choice.response }} 29 | div(ng-if="M.result") 30 | .section 31 | h3 32 | span Your house is 33 | strong {{ M.result }} 34 | 35 | p Differential Confidence: {{ M.confidence1 }}% 36 | p Average Confidence: {{ M.confidence2 }}% 37 | 38 | div(ng-repeat="outcome in M.outcomes") 39 | p(ng-if="M.result === outcome.name"). 40 | {{ outcome.message }} 41 | 42 | .section 43 | p Debug Totals: 44 | pre {{ M.results | json }} 45 | 46 | p Debug Responses: 47 | pre {{ M.responses | json }} 48 | 49 | .section 50 | h3 More 51 | p. 52 | You're a Harry Potter fan. How exciting! 53 | 54 | .section 55 | h3 Welcome 56 | p. 57 | Welcome to your house. Way to be! 58 | -------------------------------------------------------------------------------- /app/views/nav.jade: -------------------------------------------------------------------------------- 1 | //.navbar-fixed-top 2 | .navbar.navbar-default 3 | .container 4 | .navbar-header 5 | a.navbar-brand(href='/') Angular Template 6 | button.navbar-toggle(type='button', ng-init="navCollapsed = true", ng-click="navCollapsed = !navCollapsed") 7 | span.icon-bar 8 | span.icon-bar 9 | span.icon-bar 10 | #navbar-main.navbar-collapse.collapse(ng-class="!navCollapsed && 'in'") 11 | ul.nav.navbar-nav 12 | //-li.dropdown 13 | a#themes.dropdown-toggle(data-toggle='dropdown', href='#') 14 | | Themes 15 | span.caret 16 | ul.dropdown-menu(aria-labelledby='themes') 17 | li 18 | a(href='../default/') Default 19 | li.divider 20 | li 21 | a(href='../amelia/') Amelia 22 | li 23 | a(href='../cerulean/') Cerulean 24 | li 25 | a(href='../cosmo/') Cosmo 26 | li 27 | a(href='../cyborg/') Cyborg 28 | li 29 | a(href='../flatly/') Flatly 30 | li 31 | a(href='../journal/') Journal 32 | li 33 | a(href='../lumen/') Lumen 34 | li 35 | a(href='../readable/') Readable 36 | li 37 | a(href='../simplex/') Simplex 38 | li 39 | a(href='../slate/') Slate 40 | li 41 | a(href='../spacelab/') Spacelab 42 | li 43 | a(href='../superhero/') Superhero 44 | li 45 | a(href='../united/') United 46 | li 47 | a(href='../yeti/') Yeti 48 | li(ng-repeat="tab in N.tabs", ng-class="{ active: tab.active }") 49 | a(ng-href="{{tab.href}}") {{ tab.title }} 50 | ul.nav.navbar-nav.navbar-right 51 | li(ng-show="!N.session") 52 | a(href="#") Login 53 | li.dropdown(ng-show="N.session") 54 | a#account.dropdown-toggle(data-toggle='dropdown', href='#') 55 | | Account 56 | span.caret 57 | ul.dropdown-menu(aria-labelledby='account') 58 | li 59 | a(href="", ui-sref="account") Settings 60 | li.divider 61 | li 62 | a(href="", ng-click="N.logout()") Logout 63 | -------------------------------------------------------------------------------- /app/views/profile-pic.jade: -------------------------------------------------------------------------------- 1 | h3 Profile Pic 2 | //img.aj-crop(ng-src="{{ P.imageSrc }}") 3 | input( 4 | type="file" 5 | , accept="image/*" 6 | , capture="camera" 7 | , aj-change="P.getFile($files)" 8 | , aj-model="P.file" 9 | ) 10 | //- TODO , aj-file-select="P.onFileSelect($files)" 11 | 12 | h3 Crop 13 | img-cropped( 14 | src="imageSrc" 15 | , selected="selected(cords)" 16 | ) 17 | 18 | h3 Div Preview 19 | div#cropped-image( 20 | ng-show="cropped" 21 | , ng-style="{ width: P.picWidth + 'px', height: P.picHeight + 'px', overflow: 'hidden' }" 22 | ) 23 | img#preview(ng-src="{{ P.imageSrc }}") 24 | 25 | h4 Canvas Preview 26 | .canvas-preview 27 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "profilepic", 3 | "version": "0.1.0", 4 | "dependencies": { 5 | "angular": "~1.2.14", 6 | "json3": "~3.2.4", 7 | "es5-shim": "~2.1.0", 8 | "jquery": "~1.10.2", 9 | "angular-resource": "~1.2.0", 10 | "angular-cookies": "~1.2.0", 11 | "angular-sanitize": "~1.2.0", 12 | "angular-ui-router": "~0.2.0", 13 | "angular-bootstrap": "~0.10.0", 14 | "jcrop": "~0.9.12" 15 | }, 16 | "devDependencies": { 17 | "angular-mocks": "~1.2.0", 18 | "angular-scenario": "~1.2.0" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /config.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | // NOTE: grunt automatically serves pages from localhost:9003 which WILL NOT WORK (for some things) 3 | // 4 | // YOU MUST point your browser to local.ldsconnect.org:9003 or YOU WILL HATE YOUR LIFE 5 | // and spend hours debugging a problem that doesn't exist 6 | // (I've cumulatively wasted nearly a full day of my life on such imagined problems) 7 | // 8 | module.exports = { 9 | protocol: 'http' 10 | , hostname: 'local.ldsconnect.org' 11 | , port: 4005 12 | , get host() { 13 | if ( 14 | 'http' === this.protocol && '80' === this.port.toString() 15 | ||'https' === this.protocol && '443' === this.port.toString() 16 | ) { 17 | return this.hostname; 18 | } 19 | 20 | return this.hostname + ':' + this.port; 21 | } 22 | , get href() { 23 | return this.protocol + '://' + this.host; 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /karma-e2e.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration 2 | // http://karma-runner.github.io/0.10/config/configuration-file.html 3 | 4 | module.exports = function(config) { 5 | config.set({ 6 | // base path, that will be used to resolve files and exclude 7 | basePath: '', 8 | 9 | // testing framework to use (jasmine/mocha/qunit/...) 10 | frameworks: ['ng-scenario'], 11 | 12 | // list of files / patterns to load in the browser 13 | files: [ 14 | 'test/e2e/**/*.js' 15 | ], 16 | 17 | // list of files / patterns to exclude 18 | exclude: [], 19 | 20 | // web server port 21 | port: 8080, 22 | 23 | // level of logging 24 | // possible values: LOG_DISABLE || LOG_ERROR || LOG_WARN || LOG_INFO || LOG_DEBUG 25 | logLevel: config.LOG_INFO, 26 | 27 | 28 | // enable / disable watching file and executing tests whenever any file changes 29 | autoWatch: false, 30 | 31 | 32 | // Start these browsers, currently available: 33 | // - Chrome 34 | // - ChromeCanary 35 | // - Firefox 36 | // - Opera 37 | // - Safari (only Mac) 38 | // - PhantomJS 39 | // - IE (only Windows) 40 | browsers: ['Chrome'], 41 | 42 | 43 | // Continuous Integration mode 44 | // if true, it capture browsers, run tests and exit 45 | singleRun: false 46 | 47 | // Uncomment the following lines if you are using grunt's server to run the tests 48 | // proxies: { 49 | // '/': 'http://localhost:9000/' 50 | // }, 51 | // URL root prevent conflicts with the site root 52 | // urlRoot: '_karma_' 53 | }); 54 | }; 55 | -------------------------------------------------------------------------------- /karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration 2 | // http://karma-runner.github.io/0.10/config/configuration-file.html 3 | 4 | module.exports = function(config) { 5 | config.set({ 6 | // base path, that will be used to resolve files and exclude 7 | basePath: '', 8 | 9 | // testing framework to use (jasmine/mocha/qunit/...) 10 | frameworks: ['jasmine'], 11 | 12 | // list of files / patterns to load in the browser 13 | files: [ 14 | 'app/bower_components/angular/angular.js', 15 | 'app/bower_components/angular-mocks/angular-mocks.js', 16 | 'app/bower_components/angular-resource/angular-resource.js', 17 | 'app/bower_components/angular-cookies/angular-cookies.js', 18 | 'app/bower_components/angular-sanitize/angular-sanitize.js', 19 | 'app/bower_components/angular-route/angular-route.js', 20 | 'app/scripts/*.js', 21 | 'app/scripts/**/*.js', 22 | 'test/mock/**/*.js', 23 | 'test/spec/**/*.js' 24 | ], 25 | 26 | // list of files / patterns to exclude 27 | exclude: [], 28 | 29 | // web server port 30 | port: 8080, 31 | 32 | // level of logging 33 | // possible values: LOG_DISABLE || LOG_ERROR || LOG_WARN || LOG_INFO || LOG_DEBUG 34 | logLevel: config.LOG_INFO, 35 | 36 | 37 | // enable / disable watching file and executing tests whenever any file changes 38 | autoWatch: false, 39 | 40 | 41 | // Start these browsers, currently available: 42 | // - Chrome 43 | // - ChromeCanary 44 | // - Firefox 45 | // - Opera 46 | // - Safari (only Mac) 47 | // - PhantomJS 48 | // - IE (only Windows) 49 | browsers: ['Chrome'], 50 | 51 | 52 | // Continuous Integration mode 53 | // if true, it capture browsers, run tests and exit 54 | singleRun: false 55 | }); 56 | }; 57 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sortinghat", 3 | "version": "0.1.0", 4 | "dependencies": { 5 | "connect": "~2.11.2", 6 | "connect-livereload": "~0.3.1", 7 | "grunt-contrib-jade": "~0.8.0", 8 | "ssl-root-cas": "^1.0.6" 9 | }, 10 | "devDependencies": { 11 | "grunt": "~0.4.1", 12 | "grunt-autoprefixer": "~0.4.0", 13 | "grunt-concurrent": "~0.4.1", 14 | "grunt-contrib-clean": "~0.5.0", 15 | "grunt-contrib-coffee": "~0.7.0", 16 | "grunt-contrib-compass": "~0.6.0", 17 | "grunt-contrib-concat": "~0.3.0", 18 | "grunt-contrib-connect": "~0.5.0", 19 | "grunt-contrib-copy": "~0.4.1", 20 | "grunt-contrib-cssmin": "~0.7.0", 21 | "grunt-contrib-htmlmin": "~0.1.3", 22 | "grunt-contrib-imagemin": "~0.3.0", 23 | "grunt-contrib-jshint": "~0.7.1", 24 | "grunt-contrib-uglify": "~0.2.0", 25 | "grunt-contrib-watch": "~0.5.2", 26 | "grunt-google-cdn": "~0.2.0", 27 | "grunt-newer": "~0.5.4", 28 | "grunt-ngmin": "~0.0.2", 29 | "grunt-rev": "~0.1.0", 30 | "grunt-svgmin": "~0.2.0", 31 | "grunt-usemin": "~2.0.0", 32 | "jshint-stylish": "~0.1.3", 33 | "load-grunt-tasks": "~0.2.0", 34 | "time-grunt": "~0.2.1" 35 | }, 36 | "engines": { 37 | "node": ">= 0.10.26 < 2.x" 38 | }, 39 | "scripts": { 40 | "test": "grunt test" 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /runner: -------------------------------------------------------------------------------- 1 | server-runner.js -------------------------------------------------------------------------------- /server-runner.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 'use strict'; 3 | 4 | var config = require('./config') 5 | , http = require('http') 6 | , server 7 | ; 8 | 9 | config.port = process.argv[2] || config.port; 10 | config.wsport = process.argv[3] || config.wsport; 11 | 12 | server = http.createServer(require('./server')).listen(config.port, function () { 13 | console.log('Listening on ' + config.protocol + '://127.0.0.1:' + server.address().port); 14 | console.log('Listening on ' + config.protocol + '://' + server.address().address + ':' + server.address().port); 15 | console.log('Listening on ' + config.href); 16 | }); 17 | 18 | /* 19 | var https = require('https') 20 | , fs = require('fs') 21 | , path = require('path') 22 | , server 23 | , options 24 | ; 25 | 26 | options = { 27 | key: fs.readFileSync(path.join(__dirname, 'ssl', 'ldsconnect-key.pem')), 28 | ca: [ 29 | fs.readFileSync(path.join(__dirname, 'ssl', '00-equifax.pem')) 30 | , fs.readFileSync(path.join(__dirname, 'ssl', '01-rapidssl.pem')) 31 | , fs.readFileSync(path.join(__dirname, 'ssl', '02-rapidssl.pem')) 32 | ], 33 | cert: fs.readFileSync(path.join(__dirname, 'ssl', '03-ldsconnect.pem')) 34 | }; 35 | 36 | server = https.createServer(options, require('./server')).listen(config.port, function () { 37 | console.log('Listening on ' + config.protocol + '://127.0.0.1:' + server.address().port); 38 | console.log('Listening on ' + config.protocol + '://' + server.address().address + ':' + server.address().port); 39 | console.log('Listening on ' + config.href); 40 | }); 41 | */ 42 | -------------------------------------------------------------------------------- /server.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var connect = require('connect') 4 | , path = require('path') 5 | , app = connect() 6 | ; 7 | 8 | app 9 | .use(connect.compress()) 10 | ; 11 | 12 | // 13 | // Generic Template API 14 | // 15 | app 16 | .use(connect.static(path.join(__dirname, 'data'))) 17 | //.use(connect.static(path.join(__dirname, 'dist'))) 18 | //.use(connect.static(path.join(__dirname, '.tmp', 'concat'))) 19 | .use(connect.static(path.join(__dirname, 'app'))) 20 | .use(connect.static(path.join(__dirname, '.tmp'))) 21 | ; 22 | 23 | module.exports = app; 24 | -------------------------------------------------------------------------------- /test/.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 | "after": false, 23 | "afterEach": false, 24 | "angular": false, 25 | "before": false, 26 | "beforeEach": false, 27 | "browser": false, 28 | "describe": false, 29 | "expect": false, 30 | "inject": false, 31 | "it": false, 32 | "spyOn": false 33 | } 34 | } 35 | 36 | -------------------------------------------------------------------------------- /test/runner.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | End2end Test Runner 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /test/spec/controllers/nav.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Controller: NavCtrl', function () { 4 | 5 | // load the controller's module 6 | beforeEach(module('ysawardsorgApp')); 7 | 8 | var NavCtrl, 9 | scope; 10 | 11 | // Initialize the controller and a mock scope 12 | beforeEach(inject(function ($controller, $rootScope) { 13 | scope = $rootScope.$new(); 14 | NavCtrl = $controller('NavCtrl', { 15 | $scope: scope 16 | }); 17 | })); 18 | 19 | it('should attach a list of awesomeThings to the scope', function () { 20 | expect(scope.awesomeThings.length).toBe(3); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /test/spec/controllers/profile-pic.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Controller: ProfilePicCtrl', function () { 4 | 5 | // load the controller's module 6 | beforeEach(module('sortinghatApp')); 7 | 8 | var ProfilePicCtrl, 9 | scope; 10 | 11 | // Initialize the controller and a mock scope 12 | beforeEach(inject(function ($controller, $rootScope) { 13 | scope = $rootScope.$new(); 14 | ProfilePicCtrl = $controller('ProfilePicCtrl', { 15 | $scope: scope 16 | }); 17 | })); 18 | 19 | it('should attach a list of awesomeThings to the scope', function () { 20 | expect(scope.awesomeThings.length).toBe(3); 21 | }); 22 | }); 23 | --------------------------------------------------------------------------------