├── .bowerrc
├── .editorconfig
├── .gitattributes
├── .gitignore
├── .jshintrc
├── .travis.yml
├── .yo-rc.json
├── Gruntfile.js
├── README.md
├── angular-display-advanced.png
├── app
├── .buildignore
├── .htaccess
├── 404.html
├── angular.json
├── angular2.json
├── favicon.ico
├── images
│ └── yeoman.png
├── index.html
├── robots.txt
├── scripts
│ ├── app.js
│ ├── controllers
│ │ ├── directives.js
│ │ ├── module.js
│ │ ├── organization.js
│ │ └── service.js
│ ├── directives
│ │ ├── directive-example.js
│ │ ├── inner-directive.js
│ │ └── module.js
│ ├── providers
│ │ └── gravatar2.js
│ ├── routes.js
│ └── services
│ │ ├── gravatar.js
│ │ └── module.js
├── styles
│ └── main.css
└── views
│ ├── a-module.html
│ ├── directive-example.html
│ ├── directives.html
│ ├── inner-directive.html
│ ├── module.html
│ ├── organization.html
│ └── service.html
├── bower.json
└── package.json
/.bowerrc:
--------------------------------------------------------------------------------
1 | {
2 | "directory": "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 | /node_modules
2 | /dist
3 | /.tmp
4 | /.sass-cache
5 | /bower_components
6 |
--------------------------------------------------------------------------------
/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "bitwise": true,
3 | "browser": true,
4 | "curly": true,
5 | "eqeqeq": true,
6 | "esnext": true,
7 | "latedef": true,
8 | "noarg": true,
9 | "node": true,
10 | "strict": true,
11 | "undef": true,
12 | "unused": true,
13 | "globals": {
14 | "angular": false
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | sudo: false
2 | language: node_js
3 | node_js:
4 | - 'iojs'
5 | - '0.12'
6 | - '0.10'
7 | before_script:
8 | - 'npm install -g bower grunt-cli'
9 | - 'bower install'
10 |
--------------------------------------------------------------------------------
/.yo-rc.json:
--------------------------------------------------------------------------------
1 | {}
2 |
--------------------------------------------------------------------------------
/Gruntfile.js:
--------------------------------------------------------------------------------
1 | // Generated on 2015-07-18 using generator-angular 0.12.1
2 | 'use strict';
3 |
4 | // # Globbing
5 | // for performance reasons we're only matching one level down:
6 | // 'test/spec/{,*/}*.js'
7 | // use this if you want to recursively match all subfolders:
8 | // 'test/spec/**/*.js'
9 |
10 | module.exports = function (grunt) {
11 |
12 | // Time how long tasks take. Can help when optimizing build times
13 | require('time-grunt')(grunt);
14 |
15 | // Automatically load required Grunt tasks
16 | require('jit-grunt')(grunt, {
17 | useminPrepare: 'grunt-usemin',
18 | ngtemplates: 'grunt-angular-templates',
19 | cdnify: 'grunt-google-cdn'
20 | });
21 |
22 | // Configurable paths for the application
23 | var appConfig = {
24 | app: require('./bower.json').appPath || 'app',
25 | dist: 'dist'
26 | };
27 |
28 | // Define the configuration for all the tasks
29 | grunt.initConfig({
30 |
31 | // Project settings
32 | yeoman: appConfig,
33 |
34 | // Watches files for changes and runs tasks based on the changed files
35 | watch: {
36 | bower: {
37 | files: ['bower.json'],
38 | tasks: ['wiredep']
39 | },
40 | js: {
41 | files: ['<%= yeoman.app %>/scripts/{,*/}*.js'],
42 | tasks: ['newer:jshint:all'],
43 | options: {
44 | livereload: '<%= connect.options.livereload %>'
45 | }
46 | },
47 | jsTest: {
48 | files: ['test/spec/{,*/}*.js'],
49 | tasks: ['newer:jshint:test', 'karma']
50 | },
51 | styles: {
52 | files: ['<%= yeoman.app %>/styles/{,*/}*.css'],
53 | tasks: ['newer:copy:styles', 'autoprefixer']
54 | },
55 | gruntfile: {
56 | files: ['Gruntfile.js']
57 | },
58 | livereload: {
59 | options: {
60 | livereload: '<%= connect.options.livereload %>'
61 | },
62 | files: [
63 | '<%= yeoman.app %>/{,*/}*.html',
64 | '.tmp/styles/{,*/}*.css',
65 | '<%= yeoman.app %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}'
66 | ]
67 | }
68 | },
69 |
70 | // The actual grunt server settings
71 | connect: {
72 | options: {
73 | port: 9000,
74 | // Change this to '0.0.0.0' to access the server from outside.
75 | hostname: 'localhost',
76 | livereload: 35729
77 | },
78 | livereload: {
79 | options: {
80 | open: true,
81 | middleware: function (connect) {
82 | return [
83 | connect.static('.tmp'),
84 | connect().use(
85 | '/bower_components',
86 | connect.static('./bower_components')
87 | ),
88 | connect().use(
89 | '/app/styles',
90 | connect.static('./app/styles')
91 | ),
92 | connect.static(appConfig.app)
93 | ];
94 | }
95 | }
96 | },
97 | test: {
98 | options: {
99 | port: 9001,
100 | middleware: function (connect) {
101 | return [
102 | connect.static('.tmp'),
103 | connect.static('test'),
104 | connect().use(
105 | '/bower_components',
106 | connect.static('./bower_components')
107 | ),
108 | connect.static(appConfig.app)
109 | ];
110 | }
111 | }
112 | },
113 | dist: {
114 | options: {
115 | open: true,
116 | base: '<%= yeoman.dist %>'
117 | }
118 | }
119 | },
120 |
121 | // Make sure code styles are up to par and there are no obvious mistakes
122 | jshint: {
123 | options: {
124 | jshintrc: '.jshintrc',
125 | reporter: require('jshint-stylish')
126 | },
127 | all: {
128 | src: [
129 | 'Gruntfile.js',
130 | '<%= yeoman.app %>/scripts/{,*/}*.js'
131 | ]
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 | // Add vendor prefixed styles
157 | autoprefixer: {
158 | options: {
159 | browsers: ['last 1 version']
160 | },
161 | server: {
162 | options: {
163 | map: true,
164 | },
165 | files: [{
166 | expand: true,
167 | cwd: '.tmp/styles/',
168 | src: '{,*/}*.css',
169 | dest: '.tmp/styles/'
170 | }]
171 | },
172 | dist: {
173 | files: [{
174 | expand: true,
175 | cwd: '.tmp/styles/',
176 | src: '{,*/}*.css',
177 | dest: '.tmp/styles/'
178 | }]
179 | }
180 | },
181 |
182 | // Automatically inject Bower components into the app
183 | wiredep: {
184 | app: {
185 | src: ['<%= yeoman.app %>/index.html'],
186 | ignorePath: /\.\.\//
187 | },
188 | test: {
189 | devDependencies: true,
190 | src: '<%= karma.unit.configFile %>',
191 | ignorePath: /\.\.\//,
192 | fileTypes:{
193 | js: {
194 | block: /(([\s\t]*)\/{2}\s*?bower:\s*?(\S*))(\n|\r|.)*?(\/{2}\s*endbower)/gi,
195 | detect: {
196 | js: /'(.*\.js)'/gi
197 | },
198 | replace: {
199 | js: '\'{{filePath}}\','
200 | }
201 | }
202 | }
203 | }
204 | },
205 |
206 | // Renames files for browser caching purposes
207 | filerev: {
208 | dist: {
209 | src: [
210 | '<%= yeoman.dist %>/scripts/{,*/}*.js',
211 | '<%= yeoman.dist %>/styles/{,*/}*.css',
212 | '<%= yeoman.dist %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}',
213 | '<%= yeoman.dist %>/styles/fonts/*'
214 | ]
215 | }
216 | },
217 |
218 | // Reads HTML for usemin blocks to enable smart builds that automatically
219 | // concat, minify and revision files. Creates configurations in memory so
220 | // additional tasks can operate on them
221 | useminPrepare: {
222 | html: '<%= yeoman.app %>/index.html',
223 | options: {
224 | dest: '<%= yeoman.dist %>',
225 | flow: {
226 | html: {
227 | steps: {
228 | js: ['concat', 'uglifyjs'],
229 | css: ['cssmin']
230 | },
231 | post: {}
232 | }
233 | }
234 | }
235 | },
236 |
237 | // Performs rewrites based on filerev and the useminPrepare configuration
238 | usemin: {
239 | html: ['<%= yeoman.dist %>/{,*/}*.html'],
240 | css: ['<%= yeoman.dist %>/styles/{,*/}*.css'],
241 | js: ['<%= yeoman.dist %>/scripts/{,*/}*.js'],
242 | options: {
243 | assetsDirs: [
244 | '<%= yeoman.dist %>',
245 | '<%= yeoman.dist %>/images',
246 | '<%= yeoman.dist %>/styles'
247 | ],
248 | patterns: {
249 | js: [[/(images\/[^''""]*\.(png|jpg|jpeg|gif|webp|svg))/g, 'Replacing references to images']]
250 | }
251 | }
252 | },
253 |
254 | // The following *-min tasks will produce minified files in the dist folder
255 | // By default, your `index.html`'s will take care of
256 | // minification. These next options are pre-configured if you do not wish
257 | // to use the Usemin blocks.
258 | // cssmin: {
259 | // dist: {
260 | // files: {
261 | // '<%= yeoman.dist %>/styles/main.css': [
262 | // '.tmp/styles/{,*/}*.css'
263 | // ]
264 | // }
265 | // }
266 | // },
267 | // uglify: {
268 | // dist: {
269 | // files: {
270 | // '<%= yeoman.dist %>/scripts/scripts.js': [
271 | // '<%= yeoman.dist %>/scripts/scripts.js'
272 | // ]
273 | // }
274 | // }
275 | // },
276 | // concat: {
277 | // dist: {}
278 | // },
279 |
280 | imagemin: {
281 | dist: {
282 | files: [{
283 | expand: true,
284 | cwd: '<%= yeoman.app %>/images',
285 | src: '{,*/}*.{png,jpg,jpeg,gif}',
286 | dest: '<%= yeoman.dist %>/images'
287 | }]
288 | }
289 | },
290 |
291 | svgmin: {
292 | dist: {
293 | files: [{
294 | expand: true,
295 | cwd: '<%= yeoman.app %>/images',
296 | src: '{,*/}*.svg',
297 | dest: '<%= yeoman.dist %>/images'
298 | }]
299 | }
300 | },
301 |
302 | htmlmin: {
303 | dist: {
304 | options: {
305 | collapseWhitespace: true,
306 | conservativeCollapse: true,
307 | collapseBooleanAttributes: true,
308 | removeCommentsFromCDATA: true
309 | },
310 | files: [{
311 | expand: true,
312 | cwd: '<%= yeoman.dist %>',
313 | src: ['*.html'],
314 | dest: '<%= yeoman.dist %>'
315 | }]
316 | }
317 | },
318 |
319 | ngtemplates: {
320 | dist: {
321 | options: {
322 | module: 'advancedTopicsApp',
323 | htmlmin: '<%= htmlmin.dist.options %>',
324 | usemin: 'scripts/scripts.js'
325 | },
326 | cwd: '<%= yeoman.app %>',
327 | src: 'views/{,*/}*.html',
328 | dest: '.tmp/templateCache.js'
329 | }
330 | },
331 |
332 | // ng-annotate tries to make the code safe for minification automatically
333 | // by using the Angular long form for dependency injection.
334 | ngAnnotate: {
335 | dist: {
336 | files: [{
337 | expand: true,
338 | cwd: '.tmp/concat/scripts',
339 | src: '*.js',
340 | dest: '.tmp/concat/scripts'
341 | }]
342 | }
343 | },
344 |
345 | // Replace Google CDN references
346 | cdnify: {
347 | dist: {
348 | html: ['<%= yeoman.dist %>/*.html']
349 | }
350 | },
351 |
352 | // Copies remaining files to places other tasks can use
353 | copy: {
354 | dist: {
355 | files: [{
356 | expand: true,
357 | dot: true,
358 | cwd: '<%= yeoman.app %>',
359 | dest: '<%= yeoman.dist %>',
360 | src: [
361 | '*.{ico,png,txt}',
362 | '.htaccess',
363 | '*.html',
364 | 'images/{,*/}*.{webp}',
365 | 'styles/fonts/{,*/}*.*'
366 | ]
367 | }, {
368 | expand: true,
369 | cwd: '.tmp/images',
370 | dest: '<%= yeoman.dist %>/images',
371 | src: ['generated/*']
372 | }, {
373 | expand: true,
374 | cwd: 'bower_components/bootstrap/dist',
375 | src: 'fonts/*',
376 | dest: '<%= yeoman.dist %>'
377 | }]
378 | },
379 | styles: {
380 | expand: true,
381 | cwd: '<%= yeoman.app %>/styles',
382 | dest: '.tmp/styles/',
383 | src: '{,*/}*.css'
384 | }
385 | },
386 |
387 | // Run some tasks in parallel to speed up the build process
388 | concurrent: {
389 | server: [
390 | 'copy:styles'
391 | ],
392 | test: [
393 | 'copy:styles'
394 | ],
395 | dist: [
396 | 'copy:styles',
397 | 'imagemin',
398 | 'svgmin'
399 | ]
400 | },
401 |
402 | // Test settings
403 | karma: {
404 | unit: {
405 | configFile: 'test/karma.conf.js',
406 | singleRun: true
407 | }
408 | }
409 | });
410 |
411 |
412 | grunt.registerTask('serve', 'Compile then start a connect web server', function (target) {
413 | if (target === 'dist') {
414 | return grunt.task.run(['build', 'connect:dist:keepalive']);
415 | }
416 |
417 | grunt.task.run([
418 | 'clean:server',
419 | 'wiredep',
420 | 'concurrent:server',
421 | 'autoprefixer:server',
422 | 'connect:livereload',
423 | 'watch'
424 | ]);
425 | });
426 |
427 | grunt.registerTask('server', 'DEPRECATED TASK. Use the "serve" task instead', function (target) {
428 | grunt.log.warn('The `server` task has been deprecated. Use `grunt serve` to start a server.');
429 | grunt.task.run(['serve:' + target]);
430 | });
431 |
432 | grunt.registerTask('test', [
433 | 'clean:server',
434 | 'wiredep',
435 | 'concurrent:test',
436 | 'autoprefixer',
437 | 'connect:test',
438 | 'karma'
439 | ]);
440 |
441 | grunt.registerTask('build', [
442 | 'clean:dist',
443 | 'wiredep',
444 | 'useminPrepare',
445 | 'concurrent:dist',
446 | 'autoprefixer',
447 | 'ngtemplates',
448 | 'concat',
449 | 'ngAnnotate',
450 | 'copy:dist',
451 | 'cdnify',
452 | 'cssmin',
453 | 'uglify',
454 | 'filerev',
455 | 'usemin',
456 | 'htmlmin'
457 | ]);
458 |
459 | grunt.registerTask('default', [
460 | 'newer:jshint',
461 | 'test',
462 | 'build'
463 | ]);
464 | };
465 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [ ](https://angular.io)
2 |
3 | AngularJS : Advanced Topics
4 | ================
5 |
6 | A project aimed to help the user master AngularJS advanced topics. Each unit contains a tutorial with concepts, examples and best practices.
7 |
8 | Topics
9 | ================
10 | - Routing and ($routeProvider and $routeParams)
11 | - Directives ($scope and Scope)
12 | - Directives (Require and Link attributes)
13 | - Services (Factory Pattern and $resource)
14 | - Provider Service Pattern
15 |
16 | Suggested prerequisites
17 | ====================
18 | [ ](https://github.com/MartinChavez/Learn-Javascript)
19 | [ ](https://github.com/MartinChavez/HTML-CSS)
20 | [ ](https://github.com/MartinChavez/HTML-CSS-Advanced-Topics)
21 | [ ](https://github.com/MartinChavez/AngularJs-Basics)
22 |
23 | Tools
24 | ====================
25 | [ ](https://nodejs.org/)
26 | [ ](http://yeoman.io/)
27 | [ ](https://github.com/gruntjs/grunt)
28 | [ ](http://bower.io/)
29 | [ ](https://www.npmjs.com/)
30 |
31 | Routes and $routeProvider
32 | ====================
33 | ```Javascript
34 | /* Routes*/
35 | //Angular routes allow us to map URLs to use templates so that every time the current route changes,
36 | //the included view changes with it
37 |
38 | /* $routeProvider*/
39 | //$routeProvider allows you to specify Routes in the Angular application
40 |
41 | //It is a good practice to re-declare your application module in every new file
42 | angular.module('advancedTopicsApp').config(function ($routeProvider) {
43 |
44 | //Inside module.config, we can use one of $routeProvider's methods to define routes
45 |
46 | /* .when (path, route)*/
47 | //Adds a new route definition to the $route service
48 |
49 | /* .otherwise (params)*/
50 | //Sets route definition that will be used on route change when no other route definition is matched
51 |
52 | //You only need to define $routeProvider once and use method chaining
53 | $routeProvider
54 | .when('/', {
55 | /* Routing Components*/
56 | //It is possible to associate routes with templates and controllers
57 | templateUrl: 'views/organization.html',
58 | //It is a good practice to link to an already existing controller
59 | controller: 'OrganizationCtrl',
60 | //You can use 'controllerAs' to assign an alias to this controller
61 | controllerAs: 'organization'
62 | })
63 | .when('/service', {
64 | templateUrl: 'views/service.html',
65 | controller: 'ServiceCtrl',
66 | controllerAs: 'service'
67 | })
68 | .when('/directives', {
69 | templateUrl: 'views/directives.html',
70 | controller: 'DirectivesCtrl',
71 | controllerAs: 'directives'
72 | })
73 | //Declaring routes based on Id's
74 | //By passing in $routeParams we can obtain identifiers and utilize them
75 | .when('/module/:id', {
76 | templateUrl: 'views/module.html',
77 | controller: 'ModuleCtrl',
78 | controllerAs: 'module'
79 | })
80 | .otherwise({
81 | redirectTo: '/'
82 | });
83 | });
84 | ```
85 | Directives ($scope and Scope)
86 | ====================
87 | ```Javascript
88 | /*Directives*/
89 | //Directives Inherit their parent's scope by default
90 | angular.module("advancedTopicsApp")
91 | .directive("module", function () {
92 |
93 | /* $scope */
94 | return {
95 | restrict: "E",
96 | templateUrl: "views/a-module.html",
97 | //Isolating the Scope
98 |
99 | //By passing an object to the scope option, you create an isolated scope.
100 | //This tells the directive to keep scope inside itself and not to inherit or share with others
101 | scope: {
102 | //You can pass as many bindings as you need
103 |
104 | //title:"@" passes in a string
105 | title: "=", // '=' is a two-way binding,
106 | id: "="
107 | },
108 | //There are three options when binding data to an isolated scope: @,= and & characters
109 |
110 | /*Link*/
111 | //The link function is run after the directive has been compiled and linked up
112 | //This is the best place to do any DOM manipulation or logic functionality
113 |
114 | //element: refers to the outermost element of the directive
115 | //attrs stands for attributes
116 | link: function (scope, element, attrs) {
117 | element.on("click", function () {
118 | element("div.module p").toggleClass("hidden");
119 | });
120 |
121 | }
122 | // By using the $scope variable, you can avoid using alias by binding the local variables to $scope
123 | //This is very helpful in the views, since you don't need to reference any controller
124 |
125 | };
126 |
127 | /*Important: Difference between $scope and Scope Object*/
128 |
129 | //The scope object is used to isolate a directive's scope
130 | //$scope is used to set values and functions on the scope
131 | });
132 | ```
133 |
134 | Directives (Require and Link attributes)
135 | ====================
136 | ```Javascript
137 | angular.module("advancedTopicsApp")
138 | .directive("innerDirective", function () {
139 |
140 | return {
141 | restrict: "E",
142 | templateUrl: "views/inner-directive.html",
143 | scope:{
144 | innerDirective:"="
145 | },
146 | /*Require directive*/
147 | //It allows to share a controller between directives
148 | // ^ indicates that you are looking for a parent directive
149 | require:"^directiveExample",
150 |
151 | /*Link's 4th parameter*/
152 | //The required directive's controller is passed in as link's 4th parameter and can have any name
153 | link: function(scope,element,attrs,DirectivesCtrl){
154 |
155 | scope.makeActive = function(){
156 | DirectivesCtrl.setActive(scope.innerDirective);
157 | }
158 |
159 | scope.innerDirectiveActive = function (){
160 | return DirectivesCtrl.getActive() === scope.innerDirective.name;
161 |
162 | }
163 | }
164 | };
165 | });
166 | ```
167 | Services (Factory Pattern and $resource)
168 | ====================
169 | ```Javascript
170 | /* Services*/
171 | //Services should hold functions responsible for connecting and fetching data, then sharing it across our application
172 |
173 | //Service Factory
174 | //This a naming convention
175 | angular.module("advancedTopicsApp").factory("Module",function ModuleFactory($http, $resource){
176 |
177 |
178 | //By using $resource you implement all the required methods for CRUD
179 | return $resource("angular2.json",{},{
180 | update:{
181 | method:"PUT"
182 | }
183 |
184 | });
185 | ```
186 | Provider Service Pattern
187 | ====================
188 | ```Javascript
189 | /*Provider Service Recipe*/
190 | //It allows more configuration than a factory
191 |
192 | //Providers run before everything else,so the only thing you can inject to them is other providers
193 | angular.module("advancedTopicsApp").provider("Gravatar2", function Gravatar2Provider() {
194 |
195 | var avatarSize = 80; //Default size
196 | var avatarUrl = "http://www.gravatar.com/avatar/";
197 |
198 | this.setSize = function(size){
199 | avatarSize = size;
200 | };
201 |
202 |
203 | //The $get function is where you return an object and inject services
204 | this.$get = function() {
205 | return function(email) {
206 | return avatarUrl + CryptoJS.MD5(email) + "?size=" + avatarSize.toString();
207 | };
208 | };
209 |
210 | });
211 | ```
212 |
213 | Best Practices
214 | ====================
215 | ```Javascript
216 | angular.module('advancedTopicsApp')
217 | .controller('OrganizationCtrl', function ($http) {
218 |
219 | //It is a good practice to assign 'this' to a variable in order to use 'this' keyword inside the callback
220 | var controller = this;
221 | $http({method:'GET', url: 'angular.json'}).success(function(data){
222 | controller.modules = data.modules;
223 | });
224 | ```
225 |
226 | Install
227 | ====================
228 | ```Terminal
229 | npm install
230 | bower install
231 | ```
232 |
233 | Run and Play
234 | ====================
235 | ```Terminal
236 | grunt serve
237 | ```
238 |
239 |
240 | ## Author
241 |
242 | **[Martin Chavez](https://github.com/MartinChavez)**
243 |
244 | Continue Learning
245 | ====================
246 | [ ](https://github.com/MartinChavez/Learn-Javascript)
247 | [ ](https://github.com/MartinChavez/Node.js-Tutorial)
248 | [ ](https://github.com/MartinChavez/AngularJs-Basics)
249 | [ ](https://github.com/MartinChavez/AngularJS-Advanced-Topics)
250 | [ ](https://github.com/MartinChavez/CSharp)
251 | [ ](https://github.com/MartinChavez/LINQ)
252 | [ ](https://github.com/MartinChavez/jQueryBasics)
253 | [ ](https://github.com/MartinChavez/HTML-CSS)
254 | [ ](https://github.com/MartinChavez/HTML-CSS-Advanced-Topics)
255 |
--------------------------------------------------------------------------------
/angular-display-advanced.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MartinChavez/AngularJS-Advanced-Topics/321b00f08770d1279fbfda29c57437d7b2fd5945/angular-display-advanced.png
--------------------------------------------------------------------------------
/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 |
136 |
137 |
138 |
139 |
Not found :(
140 |
Sorry, but the page you were trying to view does not exist.
141 |
It looks like this was the result of either:
142 |
143 | a mistyped address
144 | an out-of-date link
145 |
146 |
149 |
150 |
151 |
152 |
153 |
--------------------------------------------------------------------------------
/app/angular.json:
--------------------------------------------------------------------------------
1 | {
2 | "modules": [
3 | {"id": "1" , "name": "ngAnimate"},
4 | {"id": "2" , "name": "ngCookies"},
5 | {"id": "3" , "name": "ngResource"}
6 | ]
7 | }
8 |
--------------------------------------------------------------------------------
/app/angular2.json:
--------------------------------------------------------------------------------
1 | [
2 | {"id": "1" , "name": "ngAnimate"},
3 | {"id": "2" , "name": "ngCookies"},
4 | {"id": "3" , "name": "ngResource"}
5 | ]
6 |
7 |
--------------------------------------------------------------------------------
/app/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MartinChavez/AngularJS-Advanced-Topics/321b00f08770d1279fbfda29c57437d7b2fd5945/app/favicon.ico
--------------------------------------------------------------------------------
/app/images/yeoman.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MartinChavez/AngularJS-Advanced-Topics/321b00f08770d1279fbfda29c57437d7b2fd5945/app/images/yeoman.png
--------------------------------------------------------------------------------
/app/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | AngularJS: Advanced Topics
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
26 |
27 |
28 |
54 |
55 |
56 |
57 |
60 |
61 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
--------------------------------------------------------------------------------
/app/robots.txt:
--------------------------------------------------------------------------------
1 | # robotstxt.org
2 |
3 | User-agent: *
4 | Disallow:
5 |
--------------------------------------------------------------------------------
/app/scripts/app.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | angular
4 | .module('advancedTopicsApp', [
5 | 'ngAnimate',
6 | 'ngCookies',
7 | 'ngResource',
8 | //Once you included ngRoute in the index.html (as a script reference),
9 | //the whole application has access to this service.
10 | //You can then use ngRoute as a dependency
11 | 'ngRoute',
12 | 'ngSanitize',
13 | 'ngTouch'
14 | ]).config(function (Gravatar2Provider){
15 |
16 | Gravatar2Provider.setSize(150);
17 | });
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/app/scripts/controllers/directives.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | angular.module('advancedTopicsApp')
4 | .controller('DirectivesCtrl', function () {
5 |
6 | /*The filter Filter*/
7 | //Selects a subset of items from an array and returns it as a new array
8 | // | filter:"a"
9 | // | filter: {category: {name: 'query'}}
10 |
11 | });
12 |
--------------------------------------------------------------------------------
/app/scripts/controllers/module.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | angular.module('advancedTopicsApp')
4 | .controller('ModuleCtrl', function ($http, $routeParams) {
5 | var controller = this;
6 |
7 | if($routeParams.id == 1){
8 | controller.module = { name: "ngAnimate"}
9 | }
10 | if($routeParams.id == 2){
11 | controller.module = { name: "ngCookies"}
12 | }
13 | if($routeParams.id == 3){
14 | controller.module = { name: "ngResource"}
15 | }
16 | });
17 |
--------------------------------------------------------------------------------
/app/scripts/controllers/organization.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | angular.module('advancedTopicsApp')
4 | .controller('OrganizationCtrl', function ($http) {
5 |
6 | //It is a good practice to assign 'this' to a variable in order to use 'this' keyword inside the callback
7 | var controller = this;
8 | $http({method:'GET', url: 'angular.json'}).success(function(data){
9 | controller.modules = data.modules;
10 | });
11 |
12 | //You can create functions that will be utilized by forms
13 | this.create = function(module){
14 |
15 | }
16 |
17 | });
18 |
--------------------------------------------------------------------------------
/app/scripts/controllers/service.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | angular.module('advancedTopicsApp')
4 | .controller('ServiceCtrl', function ($scope,$http, Module, Gravatar, Gravatar2) {
5 |
6 | var controller = $scope;
7 | controller.user = {
8 | email: "martin.chavez@live.com"
9 | };
10 |
11 | //Module.all().success(function(data){
12 | // console.log(data);
13 | // controller.modules = data.modules;
14 | // });
15 |
16 | //To fetch all of the items, you can use the query method
17 | controller.modules = Module.query();
18 |
19 | //To delete
20 | //controller.modules = Module.$delete(module);
21 |
22 | //To get a single resource
23 | //Module.get({id:2});
24 |
25 | //To create a new resource
26 | //Module.save({id:2})
27 |
28 | controller.gravatarUrl = Gravatar(controller.user.email);
29 | controller.gravatarUrl2 = Gravatar2(controller.user.email);
30 |
31 |
32 | });
33 |
--------------------------------------------------------------------------------
/app/scripts/directives/directive-example.js:
--------------------------------------------------------------------------------
1 | angular.module("advancedTopicsApp")
2 | .directive("directiveExample", function (Module) {
3 |
4 | return {
5 | replace: true,
6 | restrict: "E",
7 | templateUrl: "views/directive-example.html",
8 | link: function(scope, element, attrs){
9 | console.log(Module.query());
10 | scope.innerDirectives = Module.query();
11 | },
12 | controller: function($scope){
13 | this.setActive = function(innerDirective){
14 | $scope.active = innerDirective.active;
15 | }
16 |
17 | this.getActive = function(){
18 | return $scope.active;
19 | }
20 | }
21 | };
22 | });
23 |
--------------------------------------------------------------------------------
/app/scripts/directives/inner-directive.js:
--------------------------------------------------------------------------------
1 | angular.module("advancedTopicsApp")
2 | .directive("innerDirective", function () {
3 |
4 | return {
5 | restrict: "E",
6 | templateUrl: "views/inner-directive.html",
7 | scope:{
8 | innerDirective:"="
9 | },
10 | /*Require directive*/
11 | //It allows to share a controller between directives
12 | // ^ indicates that you are looking for a parent directive
13 | require:"^directiveExample",
14 |
15 | /*Link's 4th parameter*/
16 | //The required directive's controller is passed in as link's 4th parameter and can have any name
17 | link: function(scope,element,attrs,DirectivesCtrl){
18 |
19 | scope.makeActive = function(){
20 | DirectivesCtrl.setActive(scope.innerDirective);
21 | }
22 |
23 | scope.innerDirectiveActive = function (){
24 | return DirectivesCtrl.getActive() === scope.innerDirective.name;
25 |
26 | }
27 | }
28 | };
29 | });
30 |
--------------------------------------------------------------------------------
/app/scripts/directives/module.js:
--------------------------------------------------------------------------------
1 | /*Directives*/
2 | //Directives Inherit their parent's scope by default
3 | angular.module("advancedTopicsApp")
4 | .directive("module", function () {
5 |
6 | /* $scope */
7 | return {
8 | restrict: "E",
9 | templateUrl: "views/a-module.html",
10 | //Isolating the Scope
11 |
12 | //By passing an object to the scope option, you create an isolated scope.
13 | //This tells the directive to keep scope inside itself and not to inherit or share with others
14 | scope: {
15 | //You can pass as many bindings as you need
16 |
17 | //title:"@" passes in a string
18 | title: "=", // '=' is a two-way binding,
19 | id: "="
20 | },
21 | //There are three options when binding data to an isolated scope: @,= and & characters
22 |
23 | /*Link*/
24 | //The link function is run after the directive has been compiled and linked up
25 | //This is the best place to do any DOM manipulation or logic functionality
26 |
27 | //element: refers to the outermost element of the directive
28 | //attrs stands for attributes
29 | link: function (scope, element, attrs) {
30 | element.on("click", function () {
31 | element("div.module p").toggleClass("hidden");
32 | });
33 |
34 | }
35 | // By using the $scope variable, you can avoid using alias by binding the local variables to $scope
36 | //This is very helpful in the views, since you don't need to reference any controller
37 |
38 | };
39 |
40 | /*Important: Difference between $scope and Scope Object*/
41 |
42 | //The scope object is used to isolate a directive's scope
43 | //$scope is used to set values and functions on the scope
44 | });
45 |
--------------------------------------------------------------------------------
/app/scripts/providers/gravatar2.js:
--------------------------------------------------------------------------------
1 | /*Provider Service Recipe*/
2 | //It allows more configuration than a factory
3 |
4 | //Providers run before everything else,so the only thing you can inject to them is other providers
5 | angular.module("advancedTopicsApp").provider("Gravatar2", function Gravatar2Provider() {
6 |
7 | var avatarSize = 80; //Default size
8 | var avatarUrl = "http://www.gravatar.com/avatar/";
9 |
10 | this.setSize = function(size){
11 | avatarSize = size;
12 | };
13 |
14 |
15 | //The $get function is where you return an object and inject services
16 | this.$get = function() {
17 | return function(email) {
18 | return avatarUrl + CryptoJS.MD5(email) + "?size=" + avatarSize.toString();
19 | };
20 | };
21 |
22 | });
23 |
--------------------------------------------------------------------------------
/app/scripts/routes.js:
--------------------------------------------------------------------------------
1 | /* Routes*/
2 | //Angular routes allow us to map URLs to use templates so that every time the current route changes,
3 | //the included view changes with it
4 |
5 | /* $routeProvider*/
6 | //$routeProvider allows you to specify Routes in the Angular application
7 |
8 | //It is a good practice to re-declare your application module in every new file
9 | angular.module('advancedTopicsApp').config(function ($routeProvider) {
10 |
11 | //Inside module.config, we can use one of $routeProvider's methods to define routes
12 |
13 | /* .when (path, route)*/
14 | //Adds a new route definition to the $route service
15 |
16 | /* .otherwise (params)*/
17 | //Sets route definition that will be used on route change when no other route definition is matched
18 |
19 | //You only need to define $routeProvider once and use method chaining
20 | $routeProvider
21 | .when('/', {
22 | /* Routing Components*/
23 | //It is possible to associate routes with templates and controllers
24 | templateUrl: 'views/organization.html',
25 | //It is a good practice to link to an already existing controller
26 | controller: 'OrganizationCtrl',
27 | //You can use 'controllerAs' to assign an alias to this controller
28 | controllerAs: 'organization'
29 | })
30 | .when('/service', {
31 | templateUrl: 'views/service.html',
32 | controller: 'ServiceCtrl',
33 | controllerAs: 'service'
34 | })
35 | .when('/directives', {
36 | templateUrl: 'views/directives.html',
37 | controller: 'DirectivesCtrl',
38 | controllerAs: 'directives'
39 | })
40 | //Declaring routes based on Id's
41 | //By passing in $routeParams we can obtain identifiers and utilize them
42 | .when('/module/:id', {
43 | templateUrl: 'views/module.html',
44 | controller: 'ModuleCtrl',
45 | controllerAs: 'module'
46 | })
47 | .otherwise({
48 | redirectTo: '/'
49 | });
50 | });
51 |
--------------------------------------------------------------------------------
/app/scripts/services/gravatar.js:
--------------------------------------------------------------------------------
1 |
2 | //Service Factory
3 | angular.module("advancedTopicsApp").factory("Gravatar", function GravatarFactory() {
4 |
5 | var avatarSize = 80; //Default size
6 | var avatarUrl = "http://www.gravatar.com/avatar/";
7 |
8 |
9 | return function(email){
10 | return avatarUrl + CryptoJS.MD5(email) + "?size=" + avatarSize.toString();
11 | };
12 |
13 |
14 | });
15 |
--------------------------------------------------------------------------------
/app/scripts/services/module.js:
--------------------------------------------------------------------------------
1 | /* Services*/
2 | //Services should hold functions responsible for connecting and fetching data, then sharing it across our application
3 |
4 | //Service Factory
5 | //This a naming convention
6 | angular.module("advancedTopicsApp").factory("Module",function ModuleFactory($http, $resource){
7 |
8 |
9 | //By using $resource you implement all the required methods for CRUD
10 | return $resource("angular2.json",{},{
11 | update:{
12 | method:"PUT"
13 | }
14 |
15 | });
16 |
17 | /* Old code
18 | return {
19 | all: function() {
20 | return $http({method: 'GET', url: 'angular.json'});
21 | },
22 | create:function(module) {
23 | return $http({method: 'POST', url: 'angular.json', data: module});
24 |
25 | }
26 | }
27 | */
28 | });
29 |
--------------------------------------------------------------------------------
/app/styles/main.css:
--------------------------------------------------------------------------------
1 | .browsehappy {
2 | margin: 0.2em 0;
3 | background: #ccc;
4 | color: #000;
5 | padding: 0.2em 0;
6 | }
7 |
8 | body {
9 | padding: 0;
10 | }
11 |
12 | /* Everything but the jumbotron gets side spacing for mobile first views */
13 | .header,
14 | .marketing,
15 | .footer {
16 | padding-left: 15px;
17 | padding-right: 15px;
18 | }
19 |
20 | /* Custom page header */
21 | .header {
22 | border-bottom: 1px solid #e5e5e5;
23 | margin-bottom: 10px;
24 | }
25 | /* Make the masthead heading the same height as the navigation */
26 | .header h3 {
27 | margin-top: 0;
28 | margin-bottom: 0;
29 | line-height: 40px;
30 | padding-bottom: 19px;
31 | }
32 |
33 | /* Custom page footer */
34 | .footer {
35 | padding-top: 19px;
36 | color: #777;
37 | border-top: 1px solid #e5e5e5;
38 | }
39 |
40 | .container-narrow > hr {
41 | margin: 30px 0;
42 | }
43 |
44 | /* Main marketing message and sign up button */
45 | .jumbotron {
46 | text-align: center;
47 | border-bottom: 1px solid #e5e5e5;
48 | }
49 | .jumbotron .btn {
50 | font-size: 21px;
51 | padding: 14px 24px;
52 | }
53 |
54 | /* Supporting marketing content */
55 | .marketing {
56 | margin: 40px 0;
57 | }
58 | .marketing p + h4 {
59 | margin-top: 28px;
60 | }
61 |
62 | /* Responsive: Portrait tablets and up */
63 | @media screen and (min-width: 768px) {
64 | .container {
65 | max-width: 730px;
66 | }
67 |
68 | /* Remove the padding we set earlier */
69 | .header,
70 | .marketing,
71 | .footer {
72 | padding-left: 0;
73 | padding-right: 0;
74 | }
75 | /* Space out the masthead */
76 | .header {
77 | margin-bottom: 30px;
78 | }
79 | /* Remove the bottom border on the jumbotron for visual effect */
80 | .jumbotron {
81 | border-bottom: 0;
82 | }
83 | }
84 |
85 | .module{
86 | position: relative;
87 | }
88 |
89 | module p.hidden{
90 | display: none;
91 | }
92 |
--------------------------------------------------------------------------------
/app/views/a-module.html:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/app/views/directive-example.html:
--------------------------------------------------------------------------------
1 |
2 |
Outer Directive
3 | {{innerDirectives}}
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/app/views/directives.html:
--------------------------------------------------------------------------------
1 |
2 |
Directives
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
Directives
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/app/views/inner-directive.html:
--------------------------------------------------------------------------------
1 |
2 |
Inner directive
3 |
{{innerDirective.name}}
4 |
{{name}}
5 |
6 |
--------------------------------------------------------------------------------
/app/views/module.html:
--------------------------------------------------------------------------------
1 |
2 |
Modules
3 | {{module.module}}
4 |
5 | {{module.module.name}}
6 |
7 |
8 |
9 |
10 | {{module.module.name}}
11 |
12 |
--------------------------------------------------------------------------------
/app/views/organization.html:
--------------------------------------------------------------------------------
1 |
2 |
Organization of files
3 |
4 |
5 | It is a good practice to separate controllers, services, filters and directives into individual directories.
6 |
7 |
8 |
9 |
10 |
Controllers
11 |
12 | You should create a different file for each controller in the controllers folder
13 |
14 |
15 |
Views
16 |
17 | Unique HTML should get its own template file and place them into the templates folder.
18 | You should avoid duplication and remove redundant filename (such as 'users-index.html') and use folder hierarchy
19 | instead (users => index.html)
20 |
21 |
22 |
23 |
Index file
24 |
25 | The first file that will be loaded by the Angular App
26 |
27 |
Routes
28 |
29 | Angular routes allow us to map URLs to use templates so that every time the current route changes the included
30 | view changes with it
31 |
32 | Route steps
33 |
34 |
35 | Use ngView
36 |
37 |
38 | Load hte ngRoute library
39 |
40 |
41 | Import ngRoute module
42 |
43 |
44 | Define routes
45 |
46 |
47 |
48 |
$http service
49 |
50 |
51 |
52 | {{module}}
53 |
54 |
55 |
56 |
57 |
58 |
--------------------------------------------------------------------------------
/app/views/service.html:
--------------------------------------------------------------------------------
1 |
2 |
Services
3 |
4 |
5 | Services should hold functions responsible for connecting and fetching data, then sharing it across our application
6 |
7 |
8 |
9 |
10 |
11 |
Service Recipes
12 |
13 | Factory: Used for sharing functions and objects across an application
14 | Provider: Used for sharing functions and objects an application, but allows for configuration
15 |
16 |
Factory service
17 |
18 |
19 |
20 | {{module}}
21 |
22 |
23 |
24 |
25 |
26 |
27 | {{user.email}}
28 |
29 |
30 |
31 |
32 | {{user.email}}
33 |
34 |
35 |
--------------------------------------------------------------------------------
/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "advanced-topics",
3 | "version": "0.0.0",
4 | "dependencies": {
5 | "angular": "^1.3.0",
6 | "bootstrap": "^3.2.0",
7 | "angular-animate": "^1.3.0",
8 | "angular-cookies": "^1.3.0",
9 | "angular-resource": "^1.3.0",
10 | "angular-route": "^1.3.0",
11 | "angular-sanitize": "^1.3.0",
12 | "angular-touch": "^1.3.0"
13 | },
14 | "devDependencies": {
15 | "angular-mocks": "^1.3.0"
16 | },
17 | "appPath": "app",
18 | "moduleName": "advancedTopicsApp",
19 | "overrides": {
20 | "bootstrap": {
21 | "main": [
22 | "less/bootstrap.less",
23 | "dist/css/bootstrap.css",
24 | "dist/js/bootstrap.js"
25 | ]
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "advancedtopics",
3 | "private": true,
4 | "devDependencies": {
5 | "grunt": "^0.4.5",
6 | "grunt-angular-templates": "^0.5.7",
7 | "grunt-autoprefixer": "^2.0.0",
8 | "grunt-concurrent": "^1.0.0",
9 | "grunt-contrib-clean": "^0.6.0",
10 | "grunt-contrib-concat": "^0.5.0",
11 | "grunt-contrib-connect": "^0.9.0",
12 | "grunt-contrib-copy": "^0.7.0",
13 | "grunt-contrib-cssmin": "^0.12.0",
14 | "grunt-contrib-htmlmin": "^0.4.0",
15 | "grunt-contrib-imagemin": "^0.9.2",
16 | "grunt-contrib-jshint": "^0.11.0",
17 | "grunt-contrib-uglify": "^0.7.0",
18 | "grunt-contrib-watch": "^0.6.1",
19 | "grunt-filerev": "^2.1.2",
20 | "grunt-google-cdn": "^0.4.3",
21 | "grunt-karma": "*",
22 | "grunt-newer": "^1.1.0",
23 | "grunt-ng-annotate": "^0.9.2",
24 | "grunt-svgmin": "^2.0.0",
25 | "grunt-usemin": "^3.0.0",
26 | "grunt-wiredep": "^2.0.0",
27 | "jit-grunt": "^0.9.1",
28 | "jshint-stylish": "^1.0.0",
29 | "karma-jasmine": "*",
30 | "karma-phantomjs-launcher": "*",
31 | "time-grunt": "^1.0.0"
32 | },
33 | "engines": {
34 | "node": ">=0.10.0"
35 | },
36 | "scripts": {
37 | "test": "grunt test"
38 | }
39 | }
40 |
--------------------------------------------------------------------------------