├── LICENSE
├── Lesson01
├── 00_test_angular.html
├── 00a_test_bootstrap.html
├── 01_first_app.html
├── 02_sample_app_1.html
├── 02a_sample_app_1.html
├── angular-route.js
├── angular.min.js
├── bootstrap.min.js
├── css
│ ├── bootstrap-theme.css
│ ├── bootstrap-theme.css.map
│ ├── bootstrap-theme.min.css
│ ├── bootstrap.css
│ ├── bootstrap.css.map
│ └── bootstrap.min.css
├── fonts
│ ├── glyphicons-halflings-regular.eot
│ ├── glyphicons-halflings-regular.svg
│ ├── glyphicons-halflings-regular.ttf
│ └── glyphicons-halflings-regular.woff
├── jquery.js
└── js
│ └── bootstrap.js
├── Lesson02
├── 01_ng_repeat.html
├── 02_ng_repeat_objects.html
├── 03_objects.html
├── 04_filter1.html
├── 05_filter2.html
├── 06_filter_binding.html
├── 08_prettied_up.html
├── 08a_title_only.html
├── angular.min.js
├── bootstrap.min.js
├── css
│ ├── bootstrap-theme.css
│ ├── bootstrap-theme.css.map
│ ├── bootstrap-theme.min.css
│ ├── bootstrap.css
│ ├── bootstrap.css.map
│ └── bootstrap.min.css
├── fonts
│ ├── glyphicons-halflings-regular.eot
│ ├── glyphicons-halflings-regular.svg
│ ├── glyphicons-halflings-regular.ttf
│ └── glyphicons-halflings-regular.woff
├── jquery.min.js
├── jquery.min.map
└── js
│ └── bootstrap.js
├── Lesson03
├── 01_controller.css
├── 01_controller.html
├── 02_creation_paradigms.js
├── 03_add_album.css
├── 03_add_album.html
├── 03a_add_album.css
├── 03a_add_album.html
├── 04_validation.html
├── 05_validation.css
├── 05_validation.html
├── 06_validation.css
├── 06_validation.html
├── 07_multi_controllers_example.html
├── 08_multi_controllers.css
├── 08_multi_controllers.html
├── 08_user_partial.html
├── angular.min.js
├── bootstrap.min.js
├── css
│ ├── bootstrap-theme.css
│ ├── bootstrap-theme.css.map
│ ├── bootstrap-theme.min.css
│ ├── bootstrap.css
│ ├── bootstrap.css.map
│ └── bootstrap.min.css
├── fonts
│ ├── glyphicons-halflings-regular.eot
│ ├── glyphicons-halflings-regular.svg
│ ├── glyphicons-halflings-regular.ttf
│ └── glyphicons-halflings-regular.woff
├── jquery.min.js
├── jquery.min.map
└── js
│ └── bootstrap.js
├── Lesson04
├── 03_folders
│ ├── app
│ │ ├── app.js
│ │ ├── controllers
│ │ │ └── albumlistcontroller.js
│ │ └── partials
│ │ │ └── album_list.html
│ ├── css
│ │ ├── app.css
│ │ ├── bootstrap-theme.css
│ │ ├── bootstrap-theme.css.map
│ │ ├── bootstrap-theme.min.css
│ │ ├── bootstrap.css
│ │ ├── bootstrap.css.map
│ │ └── bootstrap.min.css
│ ├── fonts
│ │ ├── glyphicons-halflings-regular.eot
│ │ ├── glyphicons-halflings-regular.svg
│ │ ├── glyphicons-halflings-regular.ttf
│ │ └── glyphicons-halflings-regular.woff
│ ├── index.html
│ └── js
│ │ ├── angular-route.js
│ │ ├── angular.min.js
│ │ ├── bootstrap.js
│ │ ├── bootstrap.min.js
│ │ └── jquery.min.js
├── 04_album_view
│ ├── app
│ │ ├── app.js
│ │ ├── controllers
│ │ │ ├── albumlistcontroller.js
│ │ │ ├── albumviewercontroller.js
│ │ │ └── photoviewercontroller.js
│ │ └── partials
│ │ │ ├── album_list.html
│ │ │ ├── album_viewer.html
│ │ │ └── photo_viewer.html
│ ├── css
│ │ ├── app.css
│ │ ├── bootstrap-theme.css
│ │ ├── bootstrap-theme.css.map
│ │ ├── bootstrap-theme.min.css
│ │ ├── bootstrap.css
│ │ ├── bootstrap.css.map
│ │ └── bootstrap.min.css
│ ├── fonts
│ │ ├── glyphicons-halflings-regular.eot
│ │ ├── glyphicons-halflings-regular.svg
│ │ ├── glyphicons-halflings-regular.ttf
│ │ └── glyphicons-halflings-regular.woff
│ ├── index.html
│ └── js
│ │ ├── angular-route.js
│ │ ├── angular.min.js
│ │ ├── bootstrap.js
│ │ ├── bootstrap.min.js
│ │ └── jquery.min.js
└── parts01_and_02
│ ├── 01_my_first_module.css
│ ├── 01_my_first_module.html
│ ├── 02_album_list_partial.html
│ ├── 02_routes.css
│ ├── 02_routes.html
│ ├── angular-route.js
│ ├── angular.min.js
│ ├── bootstrap.min.js
│ ├── css
│ ├── bootstrap-theme.css
│ ├── bootstrap-theme.css.map
│ ├── bootstrap-theme.min.css
│ ├── bootstrap.css
│ ├── bootstrap.css.map
│ └── bootstrap.min.css
│ ├── fonts
│ ├── glyphicons-halflings-regular.eot
│ ├── glyphicons-halflings-regular.svg
│ ├── glyphicons-halflings-regular.ttf
│ └── glyphicons-halflings-regular.woff
│ ├── jquery.min.js
│ ├── jquery.min.map
│ └── js
│ └── bootstrap.js
├── Lesson05
├── 01_services
│ ├── app
│ │ ├── app.js
│ │ ├── controllers
│ │ │ ├── albumlistcontroller.js
│ │ │ ├── albumviewercontroller.js
│ │ │ └── photoviewercontroller.js
│ │ ├── partials
│ │ │ ├── album_list.html
│ │ │ ├── album_viewer.html
│ │ │ └── photo_viewer.html
│ │ └── services
│ │ │ └── albumprovider.js
│ ├── css
│ │ ├── app.css
│ │ ├── bootstrap-theme.css
│ │ ├── bootstrap-theme.css.map
│ │ ├── bootstrap-theme.min.css
│ │ ├── bootstrap.css
│ │ ├── bootstrap.css.map
│ │ └── bootstrap.min.css
│ ├── fonts
│ │ ├── glyphicons-halflings-regular.eot
│ │ ├── glyphicons-halflings-regular.svg
│ │ ├── glyphicons-halflings-regular.ttf
│ │ └── glyphicons-halflings-regular.woff
│ ├── index.html
│ └── js
│ │ ├── angular-route.js
│ │ ├── angular.min.js
│ │ ├── bootstrap.js
│ │ ├── bootstrap.min.js
│ │ └── jquery.min.js
├── 02_factories
│ ├── app
│ │ ├── app.js
│ │ ├── controllers
│ │ │ ├── albumlistcontroller.js
│ │ │ ├── albumviewercontroller.js
│ │ │ └── photoviewercontroller.js
│ │ ├── partials
│ │ │ ├── album_list.html
│ │ │ ├── album_viewer.html
│ │ │ └── photo_viewer.html
│ │ └── services
│ │ │ └── albumprovider.js
│ ├── css
│ │ ├── app.css
│ │ ├── bootstrap-theme.css
│ │ ├── bootstrap-theme.css.map
│ │ ├── bootstrap-theme.min.css
│ │ ├── bootstrap.css
│ │ ├── bootstrap.css.map
│ │ └── bootstrap.min.css
│ ├── fonts
│ │ ├── glyphicons-halflings-regular.eot
│ │ ├── glyphicons-halflings-regular.svg
│ │ ├── glyphicons-halflings-regular.ttf
│ │ └── glyphicons-halflings-regular.woff
│ ├── index.html
│ └── js
│ │ ├── angular-route.js
│ │ ├── angular.min.js
│ │ ├── bootstrap.js
│ │ ├── bootstrap.min.js
│ │ └── jquery.min.js
├── 03_useful_factories.js
├── 04_remote_data
│ ├── back
│ │ ├── index.js
│ │ ├── package.json
│ │ └── photo_albums.json
│ └── front
│ │ ├── app
│ │ ├── app.js
│ │ ├── controllers
│ │ │ ├── albumlistcontroller.js
│ │ │ ├── albumviewercontroller.js
│ │ │ └── photoviewercontroller.js
│ │ ├── partials
│ │ │ ├── album_list.html
│ │ │ ├── album_viewer.html
│ │ │ └── photo_viewer.html
│ │ └── services
│ │ │ ├── albumprovider.js
│ │ │ └── configprops.js
│ │ ├── css
│ │ ├── app.css
│ │ ├── bootstrap-theme.css
│ │ ├── bootstrap-theme.css.map
│ │ ├── bootstrap-theme.min.css
│ │ ├── bootstrap.css
│ │ ├── bootstrap.css.map
│ │ └── bootstrap.min.css
│ │ ├── fonts
│ │ ├── glyphicons-halflings-regular.eot
│ │ ├── glyphicons-halflings-regular.svg
│ │ ├── glyphicons-halflings-regular.ttf
│ │ └── glyphicons-halflings-regular.woff
│ │ ├── index.html
│ │ └── js
│ │ ├── angular-route.js
│ │ ├── angular.min.js
│ │ ├── bootstrap.js
│ │ ├── bootstrap.min.js
│ │ └── jquery.min.js
└── 05_uploads
│ ├── back
│ ├── index.js
│ ├── package.json
│ └── photo_albums.json
│ └── front
│ ├── app
│ ├── app.js
│ ├── controllers
│ │ ├── albumlistcontroller.js
│ │ ├── albumuploadcontroller.js
│ │ ├── albumviewercontroller.js
│ │ └── photoviewercontroller.js
│ ├── partials
│ │ ├── album_list.html
│ │ ├── album_uploader.html
│ │ ├── album_viewer.html
│ │ └── photo_viewer.html
│ └── services
│ │ ├── albumprovider.js
│ │ └── configprops.js
│ ├── css
│ ├── app.css
│ ├── bootstrap-theme.css
│ ├── bootstrap-theme.css.map
│ ├── bootstrap-theme.min.css
│ ├── bootstrap.css
│ ├── bootstrap.css.map
│ └── bootstrap.min.css
│ ├── fonts
│ ├── glyphicons-halflings-regular.eot
│ ├── glyphicons-halflings-regular.svg
│ ├── glyphicons-halflings-regular.ttf
│ └── glyphicons-halflings-regular.woff
│ ├── index.html
│ └── js
│ ├── angular-file-upload.js
│ ├── angular-route.js
│ ├── angular.min.js
│ ├── bootstrap.js
│ ├── bootstrap.min.js
│ └── jquery.min.js
├── Lesson06
└── filters_directives
│ ├── back
│ ├── index.js
│ ├── package.json
│ └── photo_albums.json
│ └── front
│ ├── app
│ ├── app.js
│ ├── controllers
│ │ ├── albumlistcontroller.js
│ │ ├── albumuploadcontroller.js
│ │ ├── albumviewercontroller.js
│ │ └── photoviewercontroller.js
│ ├── partials
│ │ ├── album_list.html
│ │ ├── album_uploader.html
│ │ ├── album_viewer.html
│ │ └── photo_viewer.html
│ └── services
│ │ ├── albumprovider.js
│ │ └── configprops.js
│ ├── css
│ ├── app.css
│ ├── bootstrap-theme.css
│ ├── bootstrap-theme.css.map
│ ├── bootstrap-theme.min.css
│ ├── bootstrap.css
│ ├── bootstrap.css.map
│ └── bootstrap.min.css
│ ├── fonts
│ ├── glyphicons-halflings-regular.eot
│ ├── glyphicons-halflings-regular.svg
│ ├── glyphicons-halflings-regular.ttf
│ └── glyphicons-halflings-regular.woff
│ ├── index.html
│ └── js
│ ├── angular-file-upload.js
│ ├── angular-route.js
│ ├── angular.min.js
│ ├── bootstrap.js
│ ├── bootstrap.min.js
│ └── jquery.min.js
├── Lesson07
├── 01_cleaning_up
│ ├── LICENSE
│ ├── README.md
│ ├── back
│ │ ├── index.js
│ │ ├── package.json
│ │ └── photo_albums.json
│ └── front
│ │ ├── app
│ │ ├── app.js
│ │ ├── controllers
│ │ │ ├── albumlistcontroller.js
│ │ │ ├── albumuploadcontroller.js
│ │ │ ├── albumviewcontroller.js
│ │ │ └── photoviewcontroller.js
│ │ ├── partials
│ │ │ ├── .#album_uploader.html
│ │ │ ├── album_list_partial.html
│ │ │ ├── album_uploader.html
│ │ │ ├── album_view_partial.html
│ │ │ ├── pa-album-directive.html
│ │ │ └── photo_view.html
│ │ └── services
│ │ │ └── albumservice.js
│ │ ├── css
│ │ ├── app.css
│ │ ├── bootstrap-theme.css
│ │ ├── bootstrap-theme.css.map
│ │ ├── bootstrap-theme.min.css
│ │ ├── bootstrap.css
│ │ ├── bootstrap.css.map
│ │ └── bootstrap.min.css
│ │ ├── fonts
│ │ ├── glyphicons-halflings-regular.eot
│ │ ├── glyphicons-halflings-regular.svg
│ │ ├── glyphicons-halflings-regular.ttf
│ │ └── glyphicons-halflings-regular.woff
│ │ ├── index.html
│ │ └── js
│ │ ├── angular-animate.js
│ │ ├── angular-cookies.js
│ │ ├── angular-file-upload.js
│ │ ├── angular-route.min.js
│ │ ├── angular-route.min.js.map
│ │ ├── angular.min.js
│ │ ├── bootstrap.min.js
│ │ ├── jquery.js
│ │ └── ui-bootstrap-tpls-0.10.0.min.js
└── 02_testing
│ ├── LICENSE
│ ├── README.md
│ ├── back
│ ├── index.js
│ ├── package.json
│ └── photo_albums.json
│ └── front
│ ├── app
│ ├── app.js
│ ├── controllers
│ │ ├── albumlistcontroller.js
│ │ ├── albumuploadcontroller.js
│ │ ├── albumviewcontroller.js
│ │ └── photoviewcontroller.js
│ ├── partials
│ │ ├── .#album_uploader.html
│ │ ├── album_list_partial.html
│ │ ├── album_uploader.html
│ │ ├── album_view_partial.html
│ │ ├── pa-album-directive.html
│ │ └── photo_view.html
│ └── services
│ │ └── albumservice.js
│ ├── css
│ ├── app.css
│ ├── bootstrap-theme.css
│ ├── bootstrap-theme.css.map
│ ├── bootstrap-theme.min.css
│ ├── bootstrap.css
│ ├── bootstrap.css.map
│ └── bootstrap.min.css
│ ├── fonts
│ ├── glyphicons-halflings-regular.eot
│ ├── glyphicons-halflings-regular.svg
│ ├── glyphicons-halflings-regular.ttf
│ └── glyphicons-halflings-regular.woff
│ ├── index.html
│ ├── js
│ ├── angular-animate.js
│ ├── angular-cookies.js
│ ├── angular-file-upload.js
│ ├── angular-route.min.js
│ ├── angular-route.min.js.map
│ ├── angular.min.js
│ ├── bootstrap.min.js
│ ├── jquery.js
│ └── ui-bootstrap-tpls-0.10.0.min.js
│ └── tests
│ ├── albumlistcontroller.tests.js
│ ├── angular-mocks.js
│ └── test.config.js
└── README.md
/Lesson01/00_test_angular.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Everybody wanna shout "{{ "Hello World" }}"
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Lesson01/00a_test_bootstrap.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | Everybody wanna shout "{{ "Hello World" }}"
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/Lesson01/01_first_app.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | Everybody wanna shout "{{ messageText | uppercase }}"
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/Lesson01/02_sample_app_1.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
14 | Filter list:
15 |
16 |
17 | {{ album.name }}
18 |
19 | There are {{ albums.length }} albums so far!
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/Lesson01/02a_sample_app_1.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
14 |
15 |
16 |
{{ album.name }} ({{ album.date }})
17 |
18 | {{ album.description }}
19 |
20 |
21 |
22 | There are {{ albums.length }} albums so far!
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/Lesson01/fonts/glyphicons-halflings-regular.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcwan/AngularJSLiveLessons/cef58c015affd54f775a5415d81fa4799aa76f1e/Lesson01/fonts/glyphicons-halflings-regular.eot
--------------------------------------------------------------------------------
/Lesson01/fonts/glyphicons-halflings-regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcwan/AngularJSLiveLessons/cef58c015affd54f775a5415d81fa4799aa76f1e/Lesson01/fonts/glyphicons-halflings-regular.ttf
--------------------------------------------------------------------------------
/Lesson01/fonts/glyphicons-halflings-regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcwan/AngularJSLiveLessons/cef58c015affd54f775a5415d81fa4799aa76f1e/Lesson01/fonts/glyphicons-halflings-regular.woff
--------------------------------------------------------------------------------
/Lesson02/01_ng_repeat.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/Lesson02/02_ng_repeat_objects.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
14 |
15 | There are {{albums.length}} albums so far!
16 |
17 | {{ album.name }} {{ album.title }} - ({{album.date}})
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/Lesson02/03_objects.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
16 |
17 |
18 |
19 |
20 |
21 | {{key}}
22 | {{value}}
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/Lesson02/04_filter1.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
14 |
15 | There are {{albums.length}} albums so far!
16 |
17 | {{ album.name | uppercase }} {{ album.title }} - ({{album.date}})
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/Lesson02/05_filter2.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
14 |
15 | There are {{albums.length}} albums so far!
16 |
17 | {{ album.name }} {{ album.title }} - ({{album.date}})
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/Lesson02/06_filter_binding.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
14 |
15 |
16 | {{ searchFor }}
17 |
18 | There are {{albums.length}} albums so far!
19 |
20 | {{ album.name }} {{ album.title }} - ({{album.date}})
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/Lesson02/08_prettied_up.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
{{ album.title }}
{{ album.date }}
21 |
22 | {{ album.description }}
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/Lesson02/08a_title_only.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
{{ album.title }}
{{ album.date }}
21 |
22 | {{ album.description }}
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/Lesson02/fonts/glyphicons-halflings-regular.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcwan/AngularJSLiveLessons/cef58c015affd54f775a5415d81fa4799aa76f1e/Lesson02/fonts/glyphicons-halflings-regular.eot
--------------------------------------------------------------------------------
/Lesson02/fonts/glyphicons-halflings-regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcwan/AngularJSLiveLessons/cef58c015affd54f775a5415d81fa4799aa76f1e/Lesson02/fonts/glyphicons-halflings-regular.ttf
--------------------------------------------------------------------------------
/Lesson02/fonts/glyphicons-halflings-regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcwan/AngularJSLiveLessons/cef58c015affd54f775a5415d81fa4799aa76f1e/Lesson02/fonts/glyphicons-halflings-regular.woff
--------------------------------------------------------------------------------
/Lesson03/01_controller.css:
--------------------------------------------------------------------------------
1 | body {
2 | padding: 50px;
3 | }
4 |
5 | input[type=text] {
6 | padding: 3px;
7 | border-radius: 5px;
8 | border: 1px solid #bbb;
9 | }
10 |
11 | .album {
12 | width: 300px;
13 | float: left;
14 | margin-right: 10px;
15 | }
16 |
17 | div.album div.title {
18 | float: right;
19 | }
--------------------------------------------------------------------------------
/Lesson03/01_controller.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
{{ album.title }}
{{ album.date }}
18 |
19 | {{ album.description }}
20 |
21 |
22 |
23 |
24 |
25 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/Lesson03/02_creation_paradigms.js:
--------------------------------------------------------------------------------
1 |
2 |
3 | function ObjectClass () {
4 |
5 | this.net_connection = NetConnection.create();
6 |
7 | }
8 |
9 |
10 |
11 | function ObjectClass () {
12 |
13 | var factory = _g_serviceFactory.getFactory();
14 |
15 | this.net_connection = factory.get(TYPE.NetConnection);
16 |
17 | }
18 |
19 |
20 | function ObjectClass ($net_connection) {
21 |
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/Lesson03/03_add_album.css:
--------------------------------------------------------------------------------
1 | body {
2 | padding: 50px;
3 | }
4 |
5 | input[type=text] {
6 | padding: 3px;
7 | border-radius: 5px;
8 | border: 1px solid #bbb;
9 | }
10 |
11 | textarea {
12 | padding: 3px;
13 | border-radius: 5px;
14 | border: 1px solid #bbb;
15 | }
16 |
17 | .album {
18 | width: 300px;
19 | float: left;
20 | margin-right: 10px;
21 | }
22 |
23 | div.album div.title {
24 | float: right;
25 | }
--------------------------------------------------------------------------------
/Lesson03/03_add_album.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
{{ album.title }}
{{ album.date }}
18 |
19 | {{ album.description }}
20 |
21 |
22 |
23 |
24 |
25 | Add new album
26 |
45 |
46 |
47 |
48 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
--------------------------------------------------------------------------------
/Lesson03/03a_add_album.css:
--------------------------------------------------------------------------------
1 | body {
2 | padding: 50px;
3 | }
4 |
5 | input[type=text] {
6 | padding: 3px;
7 | border-radius: 5px;
8 | border: 1px solid #bbb;
9 | }
10 |
11 | textarea {
12 | padding: 3px;
13 | border-radius: 5px;
14 | border: 1px solid #bbb;
15 | }
16 |
17 | .album {
18 | width: 300px;
19 | float: left;
20 | margin-right: 10px;
21 | }
22 |
23 | div.album div.title {
24 | float: right;
25 | }
--------------------------------------------------------------------------------
/Lesson03/03a_add_album.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
{{ album.title }}
{{ album.date }}
18 |
19 | {{ album.description }}
20 |
21 |
22 |
23 |
24 |
25 | Add new album
26 |
27 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
Add New Album
41 |
42 |
43 |
44 |
45 |
46 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
--------------------------------------------------------------------------------
/Lesson03/04_validation.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/Lesson03/05_validation.css:
--------------------------------------------------------------------------------
1 | body {
2 | padding: 50px;
3 | }
4 |
5 | input[type=text] {
6 | padding: 3px;
7 | border-radius: 5px;
8 | border: 1px solid #bbb;
9 | }
10 |
11 | .error {
12 | color: #a00;
13 | }
14 |
15 | textarea {
16 | padding: 3px;
17 | border-radius: 5px;
18 | border: 1px solid #bbb;
19 | }
20 |
21 | .album {
22 | width: 300px;
23 | float: left;
24 | margin-right: 10px;
25 | }
26 |
27 | div.album div.title {
28 | float: right;
29 | }
--------------------------------------------------------------------------------
/Lesson03/05_validation.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
{{ album.title }}
{{ album.date }}
18 |
19 | {{ album.description }}
20 |
21 |
22 |
23 |
24 |
25 | Add new album
26 |
27 |
{{add_error_text}}
28 |
29 |
37 |
38 |
39 |
40 |
41 |
42 |
49 |
50 |
Add New Album
51 |
52 |
53 |
54 |
55 |
56 |
57 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
--------------------------------------------------------------------------------
/Lesson03/06_validation.css:
--------------------------------------------------------------------------------
1 | body {
2 | padding: 50px;
3 | }
4 |
5 | input[type=text] {
6 | padding: 3px;
7 | border-radius: 5px;
8 | border: 1px solid #bbb;
9 | }
10 |
11 | .error {
12 | color: #a00;
13 | }
14 |
15 | textarea {
16 | padding: 3px;
17 | border-radius: 5px;
18 | border: 1px solid #bbb;
19 | }
20 |
21 | .album {
22 | width: 300px;
23 | float: left;
24 | margin-right: 10px;
25 | }
26 |
27 | div.album div.title {
28 | float: right;
29 | }
--------------------------------------------------------------------------------
/Lesson03/06_validation.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
{{ album.title }}
{{ album.date }}
18 |
19 | {{ album.description }}
20 |
21 |
22 |
23 |
24 |
25 | Add new album
26 |
27 |
{{add_error_text}}
28 |
29 |
37 |
38 |
39 |
40 |
41 |
42 |
49 |
50 |
Add New Album
51 |
52 |
53 |
54 |
55 |
56 |
57 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
--------------------------------------------------------------------------------
/Lesson03/07_multi_controllers_example.html:
--------------------------------------------------------------------------------
1 |
2 | Logged in {{ user.Logged_IN }}
3 | User Name {{ user.name }}
4 | etc
5 |
6 |
7 | etc
8 |
9 |
10 |
--------------------------------------------------------------------------------
/Lesson03/08_multi_controllers.css:
--------------------------------------------------------------------------------
1 | body {
2 |
3 | }
4 |
5 | input[type=text] {
6 | padding: 3px;
7 | border-radius: 5px;
8 | border: 1px solid #bbb;
9 | }
10 |
11 | .error {
12 | color: #a00;
13 | }
14 |
15 | textarea {
16 | padding: 3px;
17 | border-radius: 5px;
18 | border: 1px solid #bbb;
19 | }
20 |
21 |
22 | div#album_list {
23 | padding: 50px;
24 | }
25 |
26 |
27 | .album {
28 | width: 300px;
29 | float: left;
30 | margin-right: 10px;
31 | }
32 |
33 | div.album div.title {
34 | float: right;
35 | }
--------------------------------------------------------------------------------
/Lesson03/08_user_partial.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Logged in as: {{ user.username }}
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Lesson03/fonts/glyphicons-halflings-regular.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcwan/AngularJSLiveLessons/cef58c015affd54f775a5415d81fa4799aa76f1e/Lesson03/fonts/glyphicons-halflings-regular.eot
--------------------------------------------------------------------------------
/Lesson03/fonts/glyphicons-halflings-regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcwan/AngularJSLiveLessons/cef58c015affd54f775a5415d81fa4799aa76f1e/Lesson03/fonts/glyphicons-halflings-regular.ttf
--------------------------------------------------------------------------------
/Lesson03/fonts/glyphicons-halflings-regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcwan/AngularJSLiveLessons/cef58c015affd54f775a5415d81fa4799aa76f1e/Lesson03/fonts/glyphicons-halflings-regular.woff
--------------------------------------------------------------------------------
/Lesson04/03_folders/app/app.js:
--------------------------------------------------------------------------------
1 | var photoApp = angular.module("photoSharingApp", [ "ngRoute" ]);
2 |
3 | photoApp.config(function ($routeProvider) {
4 | $routeProvider
5 | .when("/albums", { controller: "AlbumListController", templateUrl: "/app/partials/album_list.html" })
6 | .when("/", { redirectTo: "/albums" })
7 | .otherwise({ redirectTo: "/404_page" });
8 | });
9 |
10 |
--------------------------------------------------------------------------------
/Lesson04/03_folders/app/controllers/albumlistcontroller.js:
--------------------------------------------------------------------------------
1 | (function() {
2 |
3 | function AlbumListController ($scope) {
4 |
5 | $scope.new_album = {};
6 | $scope.add_error_text = '';
7 |
8 | $scope.albums = [
9 | { name: 'madrid1309', title: 'Weekend in Madrid', date: '2013-09-01', description: 'My favourite trip' },
10 | { name: 'iceland1404', title: 'Holiday in Iceland', date: '2014-04-15', description: 'This place is cold' },
11 | { name: 'thailand1210', title: 'Surfing in Thailand', date: '2012-10-01', description: 'So hot!' },
12 | { name: 'australia1207', title: 'Wedding in Australia', date: '2012-07-31', description: 'So many kangaroos and koalas!' }
13 | ];
14 |
15 | $scope.addAlbum = function (album_data) {
16 | if (!album_data.title)
17 | $scope.add_error_text = "Missing title";
18 | else if (!album_data.date)
19 | $scope.add_error_text = "You must specify a date (yyyy/mm/dd)";
20 | else if (!album_data.description)
21 | $scope.add_error_text = "Missing description";
22 | else if (!album_data.name)
23 | $scope.add_error_text = "Short album name must be at least 6 chars (ironic, yes)";
24 | else {
25 | try {
26 | var d = new Date(album_data.date.trim());
27 | if (isNaN(d.getTime())) throw new Error("invalid date");
28 | // if we made it here the date is good
29 | $scope.albums.push(album_data);
30 | $scope.new_album = {};
31 | $scope.add_error_text = '';
32 | } catch (e) {
33 | $scope.add_error_text = "You must specify a valid date (yyyy/mm/dd)";
34 | }
35 | }
36 | };
37 | }
38 |
39 | photoApp.controller("AlbumListController", AlbumListController);
40 |
41 | })();
42 |
--------------------------------------------------------------------------------
/Lesson04/03_folders/app/partials/album_list.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
{{ album.title }}
{{ album.date }}
7 |
8 | {{ album.description }}
9 |
10 |
11 |
12 |
13 |
14 | Add new album
15 |
16 |
{{add_error_text}}
17 |
18 |
26 |
27 |
28 |
29 |
30 |
31 |
38 |
39 |
Add New Album
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/Lesson04/03_folders/css/app.css:
--------------------------------------------------------------------------------
1 | body {
2 | padding: 50px;
3 | }
4 |
5 | input[type=text] {
6 | padding: 3px;
7 | border-radius: 5px;
8 | border: 1px solid #bbb;
9 | }
10 |
11 | .error {
12 | color: #a00;
13 | }
14 |
15 | textarea {
16 | padding: 3px;
17 | border-radius: 5px;
18 | border: 1px solid #bbb;
19 | }
20 |
21 | .album {
22 | width: 300px;
23 | float: left;
24 | margin-right: 10px;
25 | }
26 |
27 | div.album div.title {
28 | float: right;
29 | }
--------------------------------------------------------------------------------
/Lesson04/03_folders/fonts/glyphicons-halflings-regular.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcwan/AngularJSLiveLessons/cef58c015affd54f775a5415d81fa4799aa76f1e/Lesson04/03_folders/fonts/glyphicons-halflings-regular.eot
--------------------------------------------------------------------------------
/Lesson04/03_folders/fonts/glyphicons-halflings-regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcwan/AngularJSLiveLessons/cef58c015affd54f775a5415d81fa4799aa76f1e/Lesson04/03_folders/fonts/glyphicons-halflings-regular.ttf
--------------------------------------------------------------------------------
/Lesson04/03_folders/fonts/glyphicons-halflings-regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcwan/AngularJSLiveLessons/cef58c015affd54f775a5415d81fa4799aa76f1e/Lesson04/03_folders/fonts/glyphicons-halflings-regular.woff
--------------------------------------------------------------------------------
/Lesson04/03_folders/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/Lesson04/04_album_view/app/app.js:
--------------------------------------------------------------------------------
1 | var photoApp = angular.module("photoSharingApp", [ "ngRoute" ]);
2 |
3 | photoApp.config(function ($routeProvider) {
4 | $routeProvider
5 | .when("/albums", { controller: "AlbumListController", templateUrl: "/app/partials/album_list.html" })
6 | .when("/album/:album_name", { controller: "AlbumViewerController", templateUrl: "/app/partials/album_viewer.html" })
7 | .when("/album/:album_name/photos/:photo_filename", { controller: "PhotoViewerController", templateUrl: "/app/partials/photo_viewer.html" })
8 | .when("/", { redirectTo: "/albums" })
9 | .otherwise({ redirectTo: "/404_page" });
10 | });
11 |
12 |
--------------------------------------------------------------------------------
/Lesson04/04_album_view/app/controllers/albumlistcontroller.js:
--------------------------------------------------------------------------------
1 | (function() {
2 |
3 | function AlbumListController ($scope) {
4 |
5 | $scope.new_album = {};
6 | $scope.add_error_text = '';
7 |
8 | $scope.albums = [
9 | { name: 'madrid1309', title: 'Weekend in Madrid', date: '2013-09-01', description: 'My favourite trip' },
10 | { name: 'iceland1404', title: 'Holiday in Iceland', date: '2014-04-15', description: 'This place is cold' },
11 | { name: 'thailand1210', title: 'Surfing in Thailand', date: '2012-10-01', description: 'So hot!' },
12 | { name: 'australia1207', title: 'Wedding in Australia', date: '2012-07-31', description: 'So many kangaroos and koalas!' }
13 | ];
14 |
15 | $scope.addAlbum = function (album_data) {
16 | if (!album_data.title)
17 | $scope.add_error_text = "Missing title";
18 | else if (!album_data.date)
19 | $scope.add_error_text = "You must specify a date (yyyy/mm/dd)";
20 | else if (!album_data.description)
21 | $scope.add_error_text = "Missing description";
22 | else if (!album_data.name)
23 | $scope.add_error_text = "Short album name must be at least 6 chars (ironic, yes)";
24 | else {
25 | try {
26 | var d = new Date(album_data.date.trim());
27 | if (isNaN(d.getTime())) throw new Error("invalid date");
28 | // if we made it here the date is good
29 | $scope.albums.push(album_data);
30 | $scope.new_album = {};
31 | $scope.add_error_text = '';
32 | } catch (e) {
33 | $scope.add_error_text = "You must specify a valid date (yyyy/mm/dd)";
34 | }
35 | }
36 | };
37 | }
38 |
39 | photoApp.controller("AlbumListController", AlbumListController);
40 |
41 | })();
42 |
--------------------------------------------------------------------------------
/Lesson04/04_album_view/app/controllers/albumviewercontroller.js:
--------------------------------------------------------------------------------
1 | (function() {
2 |
3 |
4 | function AlbumViewerController ($scope, $routeParams) {
5 | $scope.album_name = $routeParams.album_name;
6 |
7 | switch ($routeParams.album_name) {
8 | case "madrid1309":
9 | $scope.photos = [
10 | { filename: "madrid1309-001.jpg",
11 | date: "2013/09/05",
12 | description: "I love this place" },
13 | { filename: "madrid1309-002.jpg",
14 | date: "2013/09/05",
15 | description: "so much winning!!!" } ];
16 | break;
17 | default:
18 | $scope.page_loading_error = "I don't know about that album yet, sorry";
19 | }
20 |
21 | }
22 |
23 |
24 | photoApp.controller("AlbumViewerController", AlbumViewerController);
25 |
26 | })();
27 |
--------------------------------------------------------------------------------
/Lesson04/04_album_view/app/controllers/photoviewercontroller.js:
--------------------------------------------------------------------------------
1 | (function() {
2 |
3 | // what about date and description???
4 | // for next lesson!!!
5 | function PhotoViewerController ($scope, $routeParams) {
6 | $scope.album_name = $routeParams.album_name;
7 | $scope.photo_filename = $routeParams.photo_filename;
8 | }
9 |
10 |
11 | photoApp.controller("PhotoViewerController", PhotoViewerController);
12 |
13 | })();
14 |
--------------------------------------------------------------------------------
/Lesson04/04_album_view/app/partials/album_list.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
10 |
11 | {{ album.description }}
12 |
13 |
14 |
15 |
16 |
17 | Add new album
18 |
19 |
{{add_error_text}}
20 |
21 |
29 |
30 |
31 |
32 |
33 |
34 |
41 |
42 |
Add New Album
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/Lesson04/04_album_view/app/partials/album_viewer.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | {{page_loading_error}}
4 |
5 |
6 |
7 |
8 |
9 |
10 |
{{ photo.description }}
11 |
12 |
13 |
--------------------------------------------------------------------------------
/Lesson04/04_album_view/app/partials/photo_viewer.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {{album_name}}
6 |
7 |
8 |
9 |
10 |
11 |
12 | I'd like to have the description here.
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/Lesson04/04_album_view/css/app.css:
--------------------------------------------------------------------------------
1 | body {
2 | padding: 50px;
3 | }
4 |
5 | input[type=text] {
6 | padding: 3px;
7 | border-radius: 5px;
8 | border: 1px solid #bbb;
9 | }
10 |
11 | .error {
12 | color: #a00;
13 | }
14 |
15 | textarea {
16 | padding: 3px;
17 | border-radius: 5px;
18 | border: 1px solid #bbb;
19 | }
20 |
21 | .album {
22 | width: 300px;
23 | float: left;
24 | margin-right: 10px;
25 | }
26 |
27 | div.album div.title {
28 | float: right;
29 | }
30 |
31 |
32 | div.album .panel-heading a {
33 | text-decoration: none;
34 | color: white;
35 | }
36 | div.album .panel-heading a:hover {
37 | text-decoration: underline;
38 | color: white;
39 | }
--------------------------------------------------------------------------------
/Lesson04/04_album_view/fonts/glyphicons-halflings-regular.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcwan/AngularJSLiveLessons/cef58c015affd54f775a5415d81fa4799aa76f1e/Lesson04/04_album_view/fonts/glyphicons-halflings-regular.eot
--------------------------------------------------------------------------------
/Lesson04/04_album_view/fonts/glyphicons-halflings-regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcwan/AngularJSLiveLessons/cef58c015affd54f775a5415d81fa4799aa76f1e/Lesson04/04_album_view/fonts/glyphicons-halflings-regular.ttf
--------------------------------------------------------------------------------
/Lesson04/04_album_view/fonts/glyphicons-halflings-regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcwan/AngularJSLiveLessons/cef58c015affd54f775a5415d81fa4799aa76f1e/Lesson04/04_album_view/fonts/glyphicons-halflings-regular.woff
--------------------------------------------------------------------------------
/Lesson04/04_album_view/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/Lesson04/parts01_and_02/01_my_first_module.css:
--------------------------------------------------------------------------------
1 | body {
2 | padding: 50px;
3 | }
4 |
5 | input[type=text] {
6 | padding: 3px;
7 | border-radius: 5px;
8 | border: 1px solid #bbb;
9 | }
10 |
11 | .error {
12 | color: #a00;
13 | }
14 |
15 | textarea {
16 | padding: 3px;
17 | border-radius: 5px;
18 | border: 1px solid #bbb;
19 | }
20 |
21 | .album {
22 | width: 300px;
23 | float: left;
24 | margin-right: 10px;
25 | }
26 |
27 | div.album div.title {
28 | float: right;
29 | }
--------------------------------------------------------------------------------
/Lesson04/parts01_and_02/01_my_first_module.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
{{ album.title }}
{{ album.date }}
18 |
19 | {{ album.description }}
20 |
21 |
22 |
23 |
24 |
25 | Add new album
26 |
27 |
{{add_error_text}}
28 |
29 |
37 |
38 |
39 |
40 |
41 |
42 |
49 |
50 |
Add New Album
51 |
52 |
53 |
54 |
55 |
56 |
57 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
--------------------------------------------------------------------------------
/Lesson04/parts01_and_02/02_album_list_partial.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
{{ album.title }}
{{ album.date }}
7 |
8 | {{ album.description }}
9 |
10 |
11 |
12 |
13 |
14 | Add new album
15 |
16 |
{{add_error_text}}
17 |
18 |
26 |
27 |
28 |
29 |
30 |
31 |
38 |
39 |
Add New Album
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/Lesson04/parts01_and_02/02_routes.css:
--------------------------------------------------------------------------------
1 | body {
2 | padding: 50px;
3 | }
4 |
5 | input[type=text] {
6 | padding: 3px;
7 | border-radius: 5px;
8 | border: 1px solid #bbb;
9 | }
10 |
11 | .error {
12 | color: #a00;
13 | }
14 |
15 | textarea {
16 | padding: 3px;
17 | border-radius: 5px;
18 | border: 1px solid #bbb;
19 | }
20 |
21 | .album {
22 | width: 300px;
23 | float: left;
24 | margin-right: 10px;
25 | }
26 |
27 | div.album div.title {
28 | float: right;
29 | }
--------------------------------------------------------------------------------
/Lesson04/parts01_and_02/02_routes.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
--------------------------------------------------------------------------------
/Lesson04/parts01_and_02/fonts/glyphicons-halflings-regular.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcwan/AngularJSLiveLessons/cef58c015affd54f775a5415d81fa4799aa76f1e/Lesson04/parts01_and_02/fonts/glyphicons-halflings-regular.eot
--------------------------------------------------------------------------------
/Lesson04/parts01_and_02/fonts/glyphicons-halflings-regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcwan/AngularJSLiveLessons/cef58c015affd54f775a5415d81fa4799aa76f1e/Lesson04/parts01_and_02/fonts/glyphicons-halflings-regular.ttf
--------------------------------------------------------------------------------
/Lesson04/parts01_and_02/fonts/glyphicons-halflings-regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcwan/AngularJSLiveLessons/cef58c015affd54f775a5415d81fa4799aa76f1e/Lesson04/parts01_and_02/fonts/glyphicons-halflings-regular.woff
--------------------------------------------------------------------------------
/Lesson05/01_services/app/app.js:
--------------------------------------------------------------------------------
1 | var photoApp = angular.module("photoSharingApp", [ "ngRoute" ]);
2 |
3 | photoApp.config(function ($routeProvider) {
4 | $routeProvider
5 | .when("/albums", { controller: "AlbumListController", templateUrl: "/app/partials/album_list.html" })
6 | .when("/album/:album_name", { controller: "AlbumViewerController", templateUrl: "/app/partials/album_viewer.html" })
7 | .when("/album/:album_name/photos/:photo_filename", { controller: "PhotoViewerController", templateUrl: "/app/partials/photo_viewer.html" })
8 | .when("/", { redirectTo: "/albums" })
9 | .otherwise({ redirectTo: "/404_page" });
10 | });
11 |
12 |
--------------------------------------------------------------------------------
/Lesson05/01_services/app/controllers/albumlistcontroller.js:
--------------------------------------------------------------------------------
1 | (function() {
2 |
3 | function AlbumListController ($scope, albumProvider) {
4 |
5 | $scope.new_album = {};
6 | $scope.add_error_text = '';
7 |
8 | $scope.albums = albumProvider.getAlbums();
9 |
10 | $scope.addAlbum = function (album_data) {
11 | try {
12 | albumProvider.addAlbum(album_data);
13 | $scope.new_album = {};
14 | $scope.add_error_text = '';
15 |
16 | } catch (e) {
17 | if (e.message == "missing_title")
18 | $scope.add_error_text = "Missing title";
19 | else if (e.message == "bad_date")
20 | $scope.add_error_text = "You must specify a date (yyyy/mm/dd)";
21 | else if (e.message == "missing_description")
22 | $scope.add_error_text = "Missing description";
23 | else if (e.message == "bad_name")
24 | $scope.add_error_text = "Short album name must be at least 6 chars (ironic, yes)";
25 | }
26 | };
27 | }
28 |
29 | photoApp.controller("AlbumListController", AlbumListController);
30 |
31 | })();
32 |
--------------------------------------------------------------------------------
/Lesson05/01_services/app/controllers/albumviewercontroller.js:
--------------------------------------------------------------------------------
1 | (function() {
2 |
3 |
4 | function AlbumViewerController ($scope, $routeParams, albumProvider) {
5 | $scope.album_name = $routeParams.album_name;
6 |
7 | try {
8 | var album = albumProvider.getAlbumByName($scope.album_name);
9 | $scope.photos = album.photos;
10 | } catch (e) {
11 | if (e.message == "no_such_album")
12 | $scope.page_loading_error = "I don't know about that album yet, sorry";
13 | else
14 | $scope.page_loading_error = "Unexpected error. Bug!";
15 | }
16 | }
17 |
18 |
19 | photoApp.controller("AlbumViewerController", AlbumViewerController);
20 |
21 | })();
22 |
--------------------------------------------------------------------------------
/Lesson05/01_services/app/controllers/photoviewercontroller.js:
--------------------------------------------------------------------------------
1 | (function() {
2 |
3 | // what about date and description???
4 | // for next lesson!!!
5 | function PhotoViewerController ($scope, $routeParams) {
6 | $scope.album_name = $routeParams.album_name;
7 | $scope.photo_filename = $routeParams.photo_filename;
8 | }
9 |
10 |
11 | photoApp.controller("PhotoViewerController", PhotoViewerController);
12 |
13 | })();
14 |
--------------------------------------------------------------------------------
/Lesson05/01_services/app/partials/album_list.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
10 |
11 | {{ album.description }}
12 |
13 |
14 |
15 |
16 |
17 | Add new album
18 |
19 |
{{add_error_text}}
20 |
21 |
28 |
29 |
30 |
31 |
32 |
33 |
40 |
41 |
Add New Album
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/Lesson05/01_services/app/partials/album_viewer.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | {{page_loading_error}}
4 |
5 |
6 |
7 |
8 |
9 |
10 |
{{ photo.description }}
11 |
12 |
13 |
--------------------------------------------------------------------------------
/Lesson05/01_services/app/partials/photo_viewer.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {{album_name}}
6 |
7 |
8 |
9 |
10 |
11 |
12 | I'd like to have the description here.
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/Lesson05/01_services/app/services/albumprovider.js:
--------------------------------------------------------------------------------
1 | (function () {
2 |
3 | function albumProvider () {
4 |
5 | var albums = [
6 | {
7 | name: 'madrid1309',
8 | title: 'Weekend in Madrid',
9 | date: '2013-09-01',
10 | description: 'My favourite trip',
11 | photos: [
12 | {
13 | filename: "madrid1309-001.jpg",
14 | date: "2013/09/05",
15 | description: "I love this place, so much good food." },
16 | {
17 | filename: "madrid1309-002.jpg",
18 | date: "2013/09/06",
19 | description: "The museo del prado we had a wonderful time here."
20 | }
21 | ]
22 | },
23 | {
24 | name: 'iceland1404',
25 | title: 'Holiday in Iceland',
26 | date: '2014-04-15',
27 | description: 'This place is cold',
28 | photos: [
29 | {
30 | filename: "iceland1404-001.jpg",
31 | date: "2014/04/14",
32 | description: "So cold and so much snow!" },
33 | {
34 | filename: "iceland1404-002.jpg",
35 | date: "2014/04/15",
36 | description: "The northern lights are extremely clear here."
37 | }
38 | ]
39 | },
40 | {
41 | name: 'thailand1210',
42 | title: 'Surfing in Thailand',
43 | date: '2012-10-01',
44 | description: 'So hot!',
45 | photos: [
46 | {
47 | filename: "thailand1210-001.jpg",
48 | date: "2012/10/01",
49 | description: "Getting mah surf on!"
50 | },
51 | {
52 | filename: "thailand1210-002.jpg",
53 | date: "2012/10/02",
54 | description: "Thai food FTW!!!11!one!1"
55 | }
56 | ]
57 | },
58 | {
59 | name: 'australia1207',
60 | title: 'Wedding in Australia',
61 | date: '2012-07-31',
62 | description: 'So many kangaroos and koalas!',
63 | photos: [
64 | {
65 | filename: "australia1207-001.jpg",
66 | date: "2012/07/25",
67 | description: "The wedding was lovely."
68 | },
69 | {
70 | filename: "australia1207-002.jpg",
71 | date: "2012/07/27",
72 | description: "Great Ocean Road."
73 | }
74 | ]
75 | }
76 | ];
77 |
78 | this.getAlbums = function () {
79 | return albums;
80 | };
81 |
82 | this.addAlbum = function (album_data) {
83 | for (var i = 0; i < albums.length; i++) {
84 | if (albums[i].name == album_data.name)
85 | throw new Error("duplicate_album_name");
86 | }
87 |
88 | if (!album_data.title) throw new Error("missing_title");
89 | if (!album_data.description) throw new Error("missing_description");
90 | if (!album_data.date) throw new Error("bad_date");
91 |
92 | var d = new Date(album_data.date.trim());
93 | if (isNaN(d.getTime())) throw new Error("bad_date");
94 | albums.push(JSON.parse(JSON.stringify(album_data)));
95 | };
96 |
97 |
98 | this.getAlbumByName = function (name) {
99 | for (var i = 0; i < albums.length; i++) {
100 | if (albums[i].name == name)
101 | return JSON.parse(JSON.stringify(albums[i]));
102 | }
103 |
104 | throw new Error("no_such_album");
105 | };
106 | }
107 |
108 | photoApp.service("albumProvider", albumProvider);
109 |
110 | })();
111 |
--------------------------------------------------------------------------------
/Lesson05/01_services/css/app.css:
--------------------------------------------------------------------------------
1 | body {
2 | padding: 50px;
3 | }
4 |
5 | input[type=text] {
6 | padding: 3px;
7 | border-radius: 5px;
8 | border: 1px solid #bbb;
9 | }
10 |
11 | .error {
12 | color: #a00;
13 | }
14 |
15 | textarea {
16 | padding: 3px;
17 | border-radius: 5px;
18 | border: 1px solid #bbb;
19 | }
20 |
21 | .album {
22 | width: 300px;
23 | float: left;
24 | margin-right: 10px;
25 | }
26 |
27 | div.album div.title {
28 | float: right;
29 | }
30 |
31 |
32 | div.album .panel-heading a {
33 | text-decoration: none;
34 | color: white;
35 | }
36 | div.album .panel-heading a:hover {
37 | text-decoration: underline;
38 | color: white;
39 | }
--------------------------------------------------------------------------------
/Lesson05/01_services/fonts/glyphicons-halflings-regular.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcwan/AngularJSLiveLessons/cef58c015affd54f775a5415d81fa4799aa76f1e/Lesson05/01_services/fonts/glyphicons-halflings-regular.eot
--------------------------------------------------------------------------------
/Lesson05/01_services/fonts/glyphicons-halflings-regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcwan/AngularJSLiveLessons/cef58c015affd54f775a5415d81fa4799aa76f1e/Lesson05/01_services/fonts/glyphicons-halflings-regular.ttf
--------------------------------------------------------------------------------
/Lesson05/01_services/fonts/glyphicons-halflings-regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcwan/AngularJSLiveLessons/cef58c015affd54f775a5415d81fa4799aa76f1e/Lesson05/01_services/fonts/glyphicons-halflings-regular.woff
--------------------------------------------------------------------------------
/Lesson05/01_services/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/Lesson05/02_factories/app/app.js:
--------------------------------------------------------------------------------
1 | var photoApp = angular.module("photoSharingApp", [ "ngRoute" ]);
2 |
3 | photoApp.config(function ($routeProvider) {
4 | $routeProvider
5 | .when("/albums", { controller: "AlbumListController", templateUrl: "/app/partials/album_list.html" })
6 | .when("/album/:album_name", { controller: "AlbumViewerController", templateUrl: "/app/partials/album_viewer.html" })
7 | .when("/album/:album_name/photos/:photo_filename", { controller: "PhotoViewerController", templateUrl: "/app/partials/photo_viewer.html" })
8 | .when("/", { redirectTo: "/albums" })
9 | .otherwise({ redirectTo: "/404_page" });
10 | });
11 |
12 |
--------------------------------------------------------------------------------
/Lesson05/02_factories/app/controllers/albumlistcontroller.js:
--------------------------------------------------------------------------------
1 | (function() {
2 |
3 | function AlbumListController ($scope, AlbumProvider) {
4 |
5 | $scope.new_album = {};
6 | $scope.add_error_text = '';
7 |
8 | $scope.albums = AlbumProvider.getAlbums();
9 |
10 | $scope.addAlbum = function (album_data) {
11 | try {
12 | AlbumProvider.addAlbum(album_data);
13 | $scope.new_album = {};
14 | $scope.add_error_text = '';
15 |
16 | } catch (e) {
17 | if (e.message == "missing_title")
18 | $scope.add_error_text = "Missing title";
19 | else if (e.message == "bad_date")
20 | $scope.add_error_text = "You must specify a date (yyyy/mm/dd)";
21 | else if (e.message == "missing_description")
22 | $scope.add_error_text = "Missing description";
23 | else if (e.message == "bad_name")
24 | $scope.add_error_text = "Short album name must be at least 6 chars (ironic, yes)";
25 | }
26 | };
27 | }
28 |
29 | photoApp.controller("AlbumListController", AlbumListController);
30 |
31 | })();
32 |
--------------------------------------------------------------------------------
/Lesson05/02_factories/app/controllers/albumviewercontroller.js:
--------------------------------------------------------------------------------
1 | (function() {
2 |
3 |
4 | function AlbumViewerController ($scope, $routeParams, AlbumProvider) {
5 | $scope.album_name = $routeParams.album_name;
6 |
7 | try {
8 | var album = AlbumProvider.getAlbumByName($scope.album_name);
9 | $scope.photos = album.photos;
10 | } catch (e) {
11 | if (e.message == "no_such_album")
12 | $scope.page_loading_error = "I don't know about that album yet, sorry";
13 | else
14 | $scope.page_loading_error = "Unexpected error. Bug!";
15 | }
16 | }
17 |
18 |
19 | photoApp.controller("AlbumViewerController", AlbumViewerController);
20 |
21 | })();
22 |
--------------------------------------------------------------------------------
/Lesson05/02_factories/app/controllers/photoviewercontroller.js:
--------------------------------------------------------------------------------
1 | (function() {
2 |
3 | // what about date and description???
4 | // for next lesson!!!
5 | function PhotoViewerController ($scope, $routeParams) {
6 | $scope.album_name = $routeParams.album_name;
7 | $scope.photo_filename = $routeParams.photo_filename;
8 | }
9 |
10 |
11 | photoApp.controller("PhotoViewerController", PhotoViewerController);
12 |
13 | })();
14 |
--------------------------------------------------------------------------------
/Lesson05/02_factories/app/partials/album_list.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
10 |
11 | {{ album.description }}
12 |
13 |
14 |
15 |
16 |
17 | Add new album
18 |
19 |
{{add_error_text}}
20 |
21 |
28 |
29 |
30 |
31 |
32 |
33 |
40 |
41 |
Add New Album
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/Lesson05/02_factories/app/partials/album_viewer.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | {{page_loading_error}}
4 |
5 |
6 |
7 |
8 |
9 |
10 |
{{ photo.description }}
11 |
12 |
13 |
--------------------------------------------------------------------------------
/Lesson05/02_factories/app/partials/photo_viewer.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {{album_name}}
6 |
7 |
8 |
9 |
10 |
11 |
12 | I'd like to have the description here.
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/Lesson05/02_factories/css/app.css:
--------------------------------------------------------------------------------
1 | body {
2 | padding: 50px;
3 | }
4 |
5 | input[type=text] {
6 | padding: 3px;
7 | border-radius: 5px;
8 | border: 1px solid #bbb;
9 | }
10 |
11 | .error {
12 | color: #a00;
13 | }
14 |
15 | textarea {
16 | padding: 3px;
17 | border-radius: 5px;
18 | border: 1px solid #bbb;
19 | }
20 |
21 | .album {
22 | width: 300px;
23 | float: left;
24 | margin-right: 10px;
25 | }
26 |
27 | div.album div.title {
28 | float: right;
29 | }
30 |
31 |
32 | div.album .panel-heading a {
33 | text-decoration: none;
34 | color: white;
35 | }
36 | div.album .panel-heading a:hover {
37 | text-decoration: underline;
38 | color: white;
39 | }
--------------------------------------------------------------------------------
/Lesson05/02_factories/fonts/glyphicons-halflings-regular.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcwan/AngularJSLiveLessons/cef58c015affd54f775a5415d81fa4799aa76f1e/Lesson05/02_factories/fonts/glyphicons-halflings-regular.eot
--------------------------------------------------------------------------------
/Lesson05/02_factories/fonts/glyphicons-halflings-regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcwan/AngularJSLiveLessons/cef58c015affd54f775a5415d81fa4799aa76f1e/Lesson05/02_factories/fonts/glyphicons-halflings-regular.ttf
--------------------------------------------------------------------------------
/Lesson05/02_factories/fonts/glyphicons-halflings-regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcwan/AngularJSLiveLessons/cef58c015affd54f775a5415d81fa4799aa76f1e/Lesson05/02_factories/fonts/glyphicons-halflings-regular.woff
--------------------------------------------------------------------------------
/Lesson05/02_factories/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/Lesson05/03_useful_factories.js:
--------------------------------------------------------------------------------
1 |
2 | function LoginFactory () {
3 |
4 | return function (login_type) {
5 | this.perform_login = function (un, pw) {
6 | switch (login_type) {
7 | case "gplus": /* do something */ break;
8 | case "fb": /* do sth */ break;
9 | default:
10 | local_login(un, pw);
11 | };
12 | }
13 | }
14 |
15 | mymod.factory("LoginFactory", LoginFactory);
16 |
17 |
18 |
19 | function UserController ($scope, LoginFactory) {
20 | $scope.perform_login = function (login_type, un, pw) {
21 | var logger_inner = new LoginFactory(login_type);
22 |
23 | logger_inner.perform_login(un, pw);
24 | };
25 | }
26 |
27 | mymod.controller("UserController", UserController);
28 |
29 |
--------------------------------------------------------------------------------
/Lesson05/04_remote_data/back/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "photo_server",
3 | "description": "Simple Demo backend for our photo server.",
4 | "private": true,
5 | "dependencies": {
6 | "async": "0.2.x",
7 | "express": "3.x"
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/Lesson05/04_remote_data/back/photo_albums.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "name": "asdfasf241",
4 | "title": "asdf",
5 | "date": "2014/1/1",
6 | "description": "asdfasdf",
7 | "photos": []
8 | },
9 | {
10 | "name": "york1401",
11 | "title": "york",
12 | "date": "2014/10/10",
13 | "description": "asdfadf",
14 | "photos": []
15 | },
16 | {
17 | "name": "veryovely234",
18 | "title": "new album",
19 | "date": "2013/1/23",
20 | "description": "so nice",
21 | "photos": []
22 | }
23 | ]
--------------------------------------------------------------------------------
/Lesson05/04_remote_data/front/app/app.js:
--------------------------------------------------------------------------------
1 | var photoApp = angular.module("photoSharingApp", [ "ngRoute" ]);
2 |
3 | photoApp.config(function ($routeProvider) {
4 | $routeProvider
5 | .when("/albums", { controller: "AlbumListController", templateUrl: "/app/partials/album_list.html" })
6 | .when("/album/:album_name", { controller: "AlbumViewerController", templateUrl: "/app/partials/album_viewer.html" })
7 | .when("/album/:album_name/photos/:photo_filename", { controller: "PhotoViewerController", templateUrl: "/app/partials/photo_viewer.html" })
8 | .when("/", { redirectTo: "/albums" })
9 | .otherwise({ redirectTo: "/404_page" });
10 | });
11 |
12 |
--------------------------------------------------------------------------------
/Lesson05/04_remote_data/front/app/controllers/albumlistcontroller.js:
--------------------------------------------------------------------------------
1 | (function() {
2 |
3 | function AlbumListController ($scope, albumProvider, $location) {
4 |
5 | $scope.new_album = {};
6 | $scope.add_error_text = '';
7 | $scope.page_load_error = "";
8 |
9 | albumProvider.getAlbums(function (err, albums) {
10 | if (err) {
11 | $scope.page_load_error = "Unexpected error loading albums: " + e.message;
12 | } else {
13 | $scope.albums = albums;
14 | }
15 | });
16 |
17 | $scope.addAlbum = function (album_data) {
18 |
19 | albumProvider.addAlbum(album_data, function (err, results) {
20 | if (err) {
21 | if (err.code == "missing_title")
22 | $scope.add_error_text = "Missing title";
23 | else if (err.code == "bad_date")
24 | $scope.add_error_text = "You must specify a date (yyyy/mm/dd)";
25 | else if (err.code == "missing_description")
26 | $scope.add_error_text = "Missing description";
27 | else if (err.code == "bad_name")
28 | $scope.add_error_text = "Short album name must be at least 6 chars (ironic, yes)";
29 | } else {
30 | // looks good!
31 | $scope.new_album = {};
32 | $scope.add_error_text = '';
33 |
34 | // now, redirect to load in the album!
35 | $location.path("/album/" + album_data.name);
36 | }
37 |
38 | });
39 | };
40 | }
41 |
42 | photoApp.controller("AlbumListController", AlbumListController);
43 |
44 | })();
45 |
--------------------------------------------------------------------------------
/Lesson05/04_remote_data/front/app/controllers/albumviewercontroller.js:
--------------------------------------------------------------------------------
1 | (function() {
2 |
3 | function AlbumViewerController ($scope, $routeParams, albumProvider) {
4 | $scope.album_name = $routeParams.album_name;
5 |
6 | albumProvider.getAlbumByName($scope.album_name, function (err, photos) {
7 | if (err) {
8 | if (err.error == "not_found")
9 | $scope.page_load_error = "No such album. Are you calling this right?";
10 | else
11 | $scope.page_load_error = "Unexpected error loading albums: " + e.message;
12 | } else {
13 | $scope.photos = photos;
14 | }
15 | });
16 |
17 | }
18 |
19 | photoApp.controller("AlbumViewerController", AlbumViewerController);
20 |
21 | })();
22 |
--------------------------------------------------------------------------------
/Lesson05/04_remote_data/front/app/controllers/photoviewercontroller.js:
--------------------------------------------------------------------------------
1 | (function() {
2 |
3 | // what about date and description???
4 | // for next lesson!!!
5 | function PhotoViewerController ($scope, $routeParams) {
6 | $scope.album_name = $routeParams.album_name;
7 | $scope.photo_filename = $routeParams.photo_filename;
8 | }
9 |
10 |
11 | photoApp.controller("PhotoViewerController", PhotoViewerController);
12 |
13 | })();
14 |
--------------------------------------------------------------------------------
/Lesson05/04_remote_data/front/app/partials/album_list.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | {{page_load_error}}
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
15 |
16 | {{ album.description }}
17 |
18 |
19 |
20 |
21 |
22 | Add new album
23 |
24 |
{{add_error_text}}
25 |
26 |
33 |
34 |
35 |
36 |
37 |
38 |
45 |
46 |
Add New Album
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/Lesson05/04_remote_data/front/app/partials/album_viewer.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | {{page_loading_error}}
4 |
5 | {{album_name}}
6 |
7 |
8 |
9 |
10 |
11 |
12 |
{{ photo.description }}
13 |
14 |
15 |
--------------------------------------------------------------------------------
/Lesson05/04_remote_data/front/app/partials/photo_viewer.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {{album_name}}
6 |
7 |
8 |
9 |
10 |
11 |
12 | I'd like to have the description here.
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/Lesson05/04_remote_data/front/app/services/albumprovider.js:
--------------------------------------------------------------------------------
1 | (function () {
2 |
3 | function albumProvider ($http) {
4 |
5 | this.getAlbums = function (callback) {
6 | $http.get("/v1/albums.json")
7 | .success(function (data, status, headers, conf) {
8 | callback(null, data);
9 | })
10 | .error(function (data, status, headers, conf) {
11 | // just send back the error
12 | callback(data);
13 | });
14 | };
15 |
16 | this.addAlbum = function (album_data, callback) {
17 |
18 | if (!album_data.title) throw new Error("missing_title");
19 | if (!album_data.description) throw new Error("missing_description");
20 | if (!album_data.date) throw new Error("bad_date");
21 |
22 | var d = new Date(album_data.date.trim());
23 | if (isNaN(d.getTime())) throw new Error("bad_date");
24 |
25 | $http.put("/v1/albums.json", album_data)
26 | .success(function (data, status, headers, conf) {
27 | callback(null, data);
28 | })
29 | .error(function (data, status, headers, conf) {
30 | // just send back the error
31 | callback(data);
32 | });
33 | };
34 |
35 |
36 | this.getAlbumByName = function (name, callback) {
37 |
38 | $http.get("/v1/albums/" + name + "/photos.json")
39 | .success(function (data, status, headers, conf) {
40 | console.log(data);
41 | callback(null, data);
42 | })
43 | .error(function (data, status, headers, conf) {
44 | // just send back the error
45 | callback(data);
46 | });
47 | };
48 | }
49 |
50 | photoApp.service("albumProvider", albumProvider);
51 |
52 | })();
53 |
--------------------------------------------------------------------------------
/Lesson05/04_remote_data/front/app/services/configprops.js:
--------------------------------------------------------------------------------
1 | (function () {
2 |
3 | photoApp.constant("appConfigurationProps", {
4 | json_server_host: "localhost",
5 | json_server_port: 8082
6 | });
7 |
8 | })();
9 |
--------------------------------------------------------------------------------
/Lesson05/04_remote_data/front/css/app.css:
--------------------------------------------------------------------------------
1 | body {
2 | padding: 50px;
3 | }
4 |
5 | input[type=text] {
6 | padding: 3px;
7 | border-radius: 5px;
8 | border: 1px solid #bbb;
9 | }
10 |
11 | .error {
12 | color: #a00;
13 | }
14 |
15 | textarea {
16 | padding: 3px;
17 | border-radius: 5px;
18 | border: 1px solid #bbb;
19 | }
20 |
21 | .album {
22 | width: 300px;
23 | float: left;
24 | margin-right: 10px;
25 | }
26 |
27 | div.album div.title {
28 | float: right;
29 | }
30 |
31 |
32 | div.album .panel-heading a {
33 | text-decoration: none;
34 | color: white;
35 | }
36 | div.album .panel-heading a:hover {
37 | text-decoration: underline;
38 | color: white;
39 | }
--------------------------------------------------------------------------------
/Lesson05/04_remote_data/front/fonts/glyphicons-halflings-regular.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcwan/AngularJSLiveLessons/cef58c015affd54f775a5415d81fa4799aa76f1e/Lesson05/04_remote_data/front/fonts/glyphicons-halflings-regular.eot
--------------------------------------------------------------------------------
/Lesson05/04_remote_data/front/fonts/glyphicons-halflings-regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcwan/AngularJSLiveLessons/cef58c015affd54f775a5415d81fa4799aa76f1e/Lesson05/04_remote_data/front/fonts/glyphicons-halflings-regular.ttf
--------------------------------------------------------------------------------
/Lesson05/04_remote_data/front/fonts/glyphicons-halflings-regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcwan/AngularJSLiveLessons/cef58c015affd54f775a5415d81fa4799aa76f1e/Lesson05/04_remote_data/front/fonts/glyphicons-halflings-regular.woff
--------------------------------------------------------------------------------
/Lesson05/04_remote_data/front/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/Lesson05/05_uploads/back/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "photo_server",
3 | "description": "Simple Demo backend for our photo server.",
4 | "private": true,
5 | "dependencies": {
6 | "async": "0.2.x",
7 | "express": "3.x"
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/Lesson05/05_uploads/back/photo_albums.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "name": "york1402",
4 | "title": "York",
5 | "date": "2014/1/1",
6 | "description": "asdf",
7 | "photos": []
8 | },
9 | {
10 | "name": "asdfasdfzxcv",
11 | "title": "qwer",
12 | "date": "2014/1/1",
13 | "description": "zxcv",
14 | "photos": []
15 | }
16 | ]
--------------------------------------------------------------------------------
/Lesson05/05_uploads/front/app/app.js:
--------------------------------------------------------------------------------
1 | var photoApp = angular.module("photoSharingApp", [ "ngRoute", 'angularFileUpload' ]);
2 |
3 | photoApp.config(function ($routeProvider) {
4 | $routeProvider
5 | .when("/albums", { controller: "AlbumListController", templateUrl: "/app/partials/album_list.html" })
6 | .when("/album/:album_name", { controller: "AlbumViewerController", templateUrl: "/app/partials/album_viewer.html" })
7 | .when("/album/:album_name/upload", { controller: "AlbumUploadController", templateUrl: "/app/partials/album_uploader.html" })
8 | .when("/album/:album_name/photos/:photo_filename", { controller: "PhotoViewerController", templateUrl: "/app/partials/photo_viewer.html" })
9 | .when("/", { redirectTo: "/albums" })
10 | .otherwise({ redirectTo: "/404_page" });
11 | });
12 |
13 |
14 |
15 | photoApp.filter("OLD_YELLER", function () {
16 | return function (str) {
17 | if (typeof str != 'string') return str;
18 | return str.toUpperCase();
19 | }
20 | });
21 |
22 |
23 | photoApp.filter("pluralise", function () {
24 | return function (count, nouns) {
25 | if (count == 1) return count + " " + nouns.one;
26 | else return count + " " + nouns.more;
27 | }
28 | });
29 |
30 | photoApp.filter("multifieldfilter", function () {
31 | return function (obj, params) {
32 | if (!Array.isArray(obj)) return obj;
33 |
34 | if (!params.findMe) return obj;
35 | if (!params.fields || !Array.isArray(params.fields)) return obj;
36 |
37 | var out = [];
38 |
39 | for (var i = 0; i < obj.length; i++) {
40 | for (var j = 0; j < params.fields.length; j++) {
41 | if (typeof obj[i][params.fields[j]] != 'string') break;
42 | if (obj[i][params.fields[j]].indexOf(params.findMe) != -1) {
43 | out.push(obj[i]);
44 | break;
45 | }
46 | }
47 | }
48 |
49 | return out;
50 | }
51 | });
52 |
53 |
54 | photoApp.directive("mwAngry", function () {
55 | return {
56 | restrict: "A",
57 | link: function ($scope, element, attrs) {
58 | element.css({ "background-color": "yellow",
59 | color: "red" ,
60 | padding: "10px" ,
61 | "font-weight": "bold" });
62 |
63 | }
64 | }
65 | });
66 |
67 |
68 | photoApp.directive("mwAngryPlus", function () {
69 | return {
70 | restrict: "AE",
71 | template: ">:(>:(>:( ",
72 | transclude: true,
73 | link: function ($scope, element, attrs) {
74 | element.css({ "background-color": "yellow",
75 | color: "red" ,
76 | padding: "10px" ,
77 | "font-weight": "bold" });
78 |
79 | }
80 | }
81 | });
82 |
83 | photoApp.directive("mwAngryPlusPlus", function () {
84 | var angry = false;
85 | return {
86 | restrict: "AE",
87 | template: ">:(>:(>:( ",
88 | transclude: true,
89 | link: function ($scope, element, attrs, ctlr, tf) {
90 | var ot;
91 | tf(element, function (copy) {
92 | ot = copy.text();
93 | });
94 | if (ot.indexOf("HELLO") != -1) angry = true;
95 | if (angry)
96 | element.css({ "background-color": "yellow",
97 | color: "red" ,
98 | padding: "10px" ,
99 | "font-weight": "bold" });
100 | else
101 | element.html(ot);
102 | }
103 | }
104 | });
105 |
106 |
107 | photoApp.directive("paAlbum", function () {
108 | return {
109 | restrict: "AE",
110 | scope: {
111 | album: "="
112 | },
113 | template: "{{album.title}}
{{album.description}}
",
114 | link: function ($scope, element, attrs) {
115 | // don't need to do anything here.
116 | }
117 | }
118 | });
119 |
--------------------------------------------------------------------------------
/Lesson05/05_uploads/front/app/controllers/albumlistcontroller.js:
--------------------------------------------------------------------------------
1 | (function() {
2 |
3 | function AlbumListController ($scope, albumProvider, $location) {
4 |
5 | $scope.new_album = {};
6 | $scope.add_error_text = '';
7 | $scope.page_load_error = "";
8 |
9 | albumProvider.getAlbums(function (err, albums) {
10 | if (err) {
11 | $scope.page_load_error = "Unexpected error loading albums: " + e.message;
12 | } else {
13 | $scope.albums = albums;
14 | }
15 | });
16 |
17 | $scope.addAlbum = function (album_data) {
18 |
19 | albumProvider.addAlbum(album_data, function (err, results) {
20 | if (err) {
21 | if (err.code == "missing_title")
22 | $scope.add_error_text = "Missing title";
23 | else if (err.code == "bad_date")
24 | $scope.add_error_text = "You must specify a date (yyyy/mm/dd)";
25 | else if (err.code == "missing_description")
26 | $scope.add_error_text = "Missing description";
27 | else if (err.code == "bad_name")
28 | $scope.add_error_text = "Short album name must be at least 6 chars (ironic, yes)";
29 | } else {
30 | // looks good!
31 | $scope.new_album = {};
32 | $scope.add_error_text = '';
33 |
34 | // now, redirect to load in the album!
35 | $location.path("/album/" + album_data.name);
36 | }
37 |
38 | });
39 | };
40 | }
41 |
42 | photoApp.controller("AlbumListController", AlbumListController);
43 |
44 | })();
45 |
--------------------------------------------------------------------------------
/Lesson05/05_uploads/front/app/controllers/albumuploadcontroller.js:
--------------------------------------------------------------------------------
1 | (function () {
2 |
3 | function AlbumUploadController ($scope, $location, $routeParams, albumProvider) {
4 | $scope.album_name = $routeParams.album_name;
5 | $scope.page_load_error = "";
6 | $scope.done_uploading = false;
7 |
8 | // ADD FIRST!
9 | albumProvider.getAlbumByName($scope.album_name, function (err, photos) {
10 | if (err) {
11 | if (err.error == "not_found")
12 | $scope.page_load_error = "No such album. Are you calling this right?";
13 | else
14 | $scope.page_load_error = "Unexpected error loading albums: " + err.message;
15 | } else {
16 | $scope.photos = photos;
17 | }
18 | });
19 |
20 | $scope.uploader = albumProvider.getUploader($scope.album_name, $scope);
21 |
22 |
23 |
24 | $scope.uploader.bind("completeall", function (event, items) {
25 | $scope.done_uploading = true;
26 | });
27 |
28 |
29 | $scope.uploadFiles = function () {
30 | $scope.uploader.uploadAll();
31 | }
32 |
33 |
34 |
35 | // FOR DESCRIPTIONS
36 | $scope.descriptions = {};
37 | $scope.uploader.bind('beforeupload', function (event, item) {
38 | var fn = item.file.name;
39 | var d = item.file.lastModifiedDate;
40 | item.formData = [{
41 | filename: _fix_filename(item.file.name),
42 | description: $scope.descriptions[item.file.name],
43 | date: d.getFullYear() + "/" + d.getMonth() + "/" + d.getDate()
44 | } ];
45 | });
46 |
47 |
48 | }
49 |
50 | photoApp.controller("AlbumUploadController", AlbumUploadController);
51 |
52 |
53 | /**
54 | * we'll be super fussy and only allow alnum, -, _, and .
55 | */
56 | function _fix_filename(fn) {
57 | if (!fn || fn.length == 0) return "unknown";
58 |
59 | var r = new RegExp("^[a-zA-Z0-9\\-_.]+$");
60 | var out = "";
61 |
62 | for (var i = 0; i < fn.length; i++) {
63 | if (r.exec(fn[i]) != null)
64 | out += fn[i];
65 | }
66 |
67 | if (!out) out = "unknown_" + (new Date()).getTime();
68 | return out;
69 | }
70 |
71 |
72 |
73 | })();
74 |
--------------------------------------------------------------------------------
/Lesson05/05_uploads/front/app/controllers/albumviewercontroller.js:
--------------------------------------------------------------------------------
1 | (function() {
2 |
3 | function AlbumViewerController ($scope, $location, $routeParams, albumProvider) {
4 | $scope.album_name = $routeParams.album_name;
5 | $scope.page_load_error = "";
6 |
7 | albumProvider.getAlbumByName($scope.album_name, function (err, photos) {
8 | if (err) {
9 | if (err.error == "not_found")
10 | $scope.page_load_error = "No such album. Are you calling this right?";
11 | else
12 | $scope.page_load_error = "Unexpected error loading albums: " + err.message;
13 | } else {
14 | $scope.photos = photos;
15 | }
16 | });
17 | }
18 |
19 | photoApp.controller("AlbumViewerController", AlbumViewerController);
20 |
21 | })();
22 |
--------------------------------------------------------------------------------
/Lesson05/05_uploads/front/app/controllers/photoviewercontroller.js:
--------------------------------------------------------------------------------
1 | (function() {
2 |
3 | // what about date and description???
4 | // for next lesson!!!
5 | function PhotoViewerController ($scope, $routeParams) {
6 | $scope.album_name = $routeParams.album_name;
7 | $scope.photo_filename = $routeParams.photo_filename;
8 | }
9 |
10 |
11 | photoApp.controller("PhotoViewerController", PhotoViewerController);
12 |
13 | })();
14 |
--------------------------------------------------------------------------------
/Lesson05/05_uploads/front/app/partials/album_list.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | {{page_load_error}}
4 |
5 |
6 | HELLO THERE
7 |
8 | Displaying {{ albums.length | pluralise:{one:"city", more:"cities"} }}
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
23 |
24 | {{ album.description }}
25 |
26 |
27 |
28 |
29 |
30 | Add new album
31 |
32 |
{{add_error_text}}
33 |
34 |
41 |
42 |
43 |
44 |
45 |
46 |
53 |
54 |
Add New Album
55 |
56 |
57 |
58 |
--------------------------------------------------------------------------------
/Lesson05/05_uploads/front/app/partials/album_uploader.html:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 | {{page_load_error}}
7 |
8 |
9 |
10 |
11 |
12 |
13 |
Name: {{ item.file.name }}
14 |
Size: {{ item.file.size/1024/1024|number:2 }} Mb
15 |
16 | Description:
17 |
18 |
19 |
20 |
21 | Upload Progress: {{ item.progress }}
22 |
25 |
26 |
27 |
28 | Remove
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 | Total progress: {{ uploader.progress }}
37 |
40 |
41 |
Upload all
42 |
Cancel all
43 |
Remove all
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
58 |
--------------------------------------------------------------------------------
/Lesson05/05_uploads/front/app/partials/album_viewer.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | {{page_load_error}}
4 |
5 | {{album_name}}
6 |
7 |
8 |
9 |
10 |
11 |
12 |
{{ photo.description }}
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 | Add files to this album
21 |
22 |
--------------------------------------------------------------------------------
/Lesson05/05_uploads/front/app/partials/photo_viewer.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {{album_name}}
6 |
7 |
8 |
9 |
10 |
11 |
12 | I'd like to have the description here.
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/Lesson05/05_uploads/front/app/services/albumprovider.js:
--------------------------------------------------------------------------------
1 | (function () {
2 |
3 | function albumProvider ($http, $fileUploader) {
4 |
5 | this.getUploader = function (album_name, scope) {
6 | // create a uploader with options
7 | return $fileUploader.create({
8 | scope: scope,
9 | method: "PUT",
10 | url: "/v1/albums/" + album_name + "/photos.json"
11 | });
12 | };
13 |
14 | this.getAlbums = function (callback) {
15 | $http.get("/v1/albums.json")
16 | .success(function (data, status, headers, conf) {
17 | callback(null, data);
18 | })
19 | .error(function (data, status, headers, conf) {
20 | // just send back the error
21 | callback(data);
22 | });
23 | };
24 |
25 | this.addAlbum = function (album_data, callback) {
26 |
27 | if (!album_data.title) throw new Error("missing_title");
28 | if (!album_data.description) throw new Error("missing_description");
29 | if (!album_data.date) throw new Error("bad_date");
30 |
31 | var d = new Date(album_data.date.trim());
32 | if (isNaN(d.getTime())) throw new Error("bad_date");
33 |
34 | $http.put("/v1/albums.json", album_data)
35 | .success(function (data, status, headers, conf) {
36 | callback(null, data);
37 | })
38 | .error(function (data, status, headers, conf) {
39 | // just send back the error
40 | callback(data);
41 | });
42 | };
43 |
44 |
45 | this.getAlbumByName = function (name, callback) {
46 | $http.get("/v1/albums/" + name + "/photos.json")
47 | .success(function (data, status, headers, conf) {
48 | callback(null, data);
49 | })
50 | .error(function (data, status, headers, conf) {
51 | // just send back the error
52 | callback(data);
53 | });
54 | };
55 | }
56 |
57 | photoApp.service("albumProvider", albumProvider);
58 |
59 | })();
60 |
--------------------------------------------------------------------------------
/Lesson05/05_uploads/front/app/services/configprops.js:
--------------------------------------------------------------------------------
1 | (function () {
2 |
3 | photoApp.constant("appConfigurationProps", {
4 | json_server_host: "localhost",
5 | json_server_port: 8082
6 | });
7 |
8 | })();
9 |
--------------------------------------------------------------------------------
/Lesson05/05_uploads/front/css/app.css:
--------------------------------------------------------------------------------
1 | body {
2 | padding: 50px;
3 | }
4 |
5 | input[type=text] {
6 | padding: 3px;
7 | border-radius: 5px;
8 | border: 1px solid #bbb;
9 | }
10 |
11 | .error {
12 | color: #a00;
13 | }
14 |
15 | textarea {
16 | padding: 3px;
17 | border-radius: 5px;
18 | border: 1px solid #bbb;
19 | }
20 |
21 | .album {
22 | width: 300px;
23 | float: left;
24 | margin-right: 10px;
25 | }
26 |
27 | div.album div.title {
28 | float: right;
29 | }
30 |
31 |
32 | div.album .panel-heading a {
33 | text-decoration: none;
34 | color: white;
35 | }
36 | div.album .panel-heading a:hover {
37 | text-decoration: underline;
38 | color: white;
39 | }
--------------------------------------------------------------------------------
/Lesson05/05_uploads/front/fonts/glyphicons-halflings-regular.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcwan/AngularJSLiveLessons/cef58c015affd54f775a5415d81fa4799aa76f1e/Lesson05/05_uploads/front/fonts/glyphicons-halflings-regular.eot
--------------------------------------------------------------------------------
/Lesson05/05_uploads/front/fonts/glyphicons-halflings-regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcwan/AngularJSLiveLessons/cef58c015affd54f775a5415d81fa4799aa76f1e/Lesson05/05_uploads/front/fonts/glyphicons-halflings-regular.ttf
--------------------------------------------------------------------------------
/Lesson05/05_uploads/front/fonts/glyphicons-halflings-regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcwan/AngularJSLiveLessons/cef58c015affd54f775a5415d81fa4799aa76f1e/Lesson05/05_uploads/front/fonts/glyphicons-halflings-regular.woff
--------------------------------------------------------------------------------
/Lesson05/05_uploads/front/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/Lesson06/filters_directives/back/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "photo_server",
3 | "description": "Simple Demo backend for our photo server.",
4 | "private": true,
5 | "dependencies": {
6 | "async": "0.2.x",
7 | "express": "3.x"
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/Lesson06/filters_directives/back/photo_albums.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "name": "york1402",
4 | "title": "York",
5 | "date": "2014/1/1",
6 | "description": "asdf",
7 | "photos": []
8 | },
9 | {
10 | "name": "asdfasdfzxcv",
11 | "title": "qwer",
12 | "date": "2014/1/1",
13 | "description": "zxcv",
14 | "photos": []
15 | }
16 | ]
--------------------------------------------------------------------------------
/Lesson06/filters_directives/front/app/app.js:
--------------------------------------------------------------------------------
1 | var photoApp = angular.module("photoSharingApp", [ "ngRoute", 'angularFileUpload' ]);
2 |
3 | photoApp.config(function ($routeProvider) {
4 | $routeProvider
5 | .when("/albums", { controller: "AlbumListController", templateUrl: "/app/partials/album_list.html" })
6 | .when("/album/:album_name", { controller: "AlbumViewerController", templateUrl: "/app/partials/album_viewer.html" })
7 | .when("/album/:album_name/upload", { controller: "AlbumUploadController", templateUrl: "/app/partials/album_uploader.html" })
8 | .when("/album/:album_name/photos/:photo_filename", { controller: "PhotoViewerController", templateUrl: "/app/partials/photo_viewer.html" })
9 | .when("/", { redirectTo: "/albums" })
10 | .otherwise({ redirectTo: "/404_page" });
11 | });
12 |
13 |
14 |
15 | photoApp.filter("OLD_YELLER", function () {
16 | return function (str) {
17 | if (typeof str != 'string') return str;
18 | return str.toUpperCase();
19 | }
20 | });
21 |
22 |
23 | photoApp.filter("pluralise", function () {
24 | return function (count, nouns) {
25 | if (count == 1) return count + " " + nouns.one;
26 | else return count + " " + nouns.more;
27 | }
28 | });
29 |
30 | photoApp.filter("multifieldfilter", function () {
31 | return function (obj, params) {
32 | if (!Array.isArray(obj)) return obj;
33 |
34 | if (!params.findMe) return obj;
35 | if (!params.fields || !Array.isArray(params.fields)) return obj;
36 |
37 | var out = [];
38 |
39 | for (var i = 0; i < obj.length; i++) {
40 | for (var j = 0; j < params.fields.length; j++) {
41 | if (typeof obj[i][params.fields[j]] != 'string') break;
42 | if (obj[i][params.fields[j]].indexOf(params.findMe) != -1) {
43 | out.push(obj[i]);
44 | break;
45 | }
46 | }
47 | }
48 |
49 | return out;
50 | }
51 | });
52 |
53 |
54 | photoApp.directive("mwAngry", function () {
55 | return {
56 | restrict: "A",
57 | link: function ($scope, element, attrs) {
58 | element.css({ "background-color": "yellow",
59 | color: "red" ,
60 | padding: "10px" ,
61 | "font-weight": "bold" });
62 |
63 | }
64 | }
65 | });
66 |
67 |
68 | photoApp.directive("mwAngryPlus", function () {
69 | return {
70 | restrict: "AE",
71 | template: ">:(>:(>:( ",
72 | transclude: true,
73 | link: function ($scope, element, attrs) {
74 | element.css({ "background-color": "yellow",
75 | color: "red" ,
76 | padding: "10px" ,
77 | "font-weight": "bold" });
78 |
79 | }
80 | }
81 | });
82 |
83 |
84 |
85 | photoApp.directive("paAlbum", function () {
86 | return {
87 | restrict: "AE",
88 | scope: {
89 | album: "="
90 | },
91 | template: "{{album.title}}
{{album.description}}
",
92 | link: function ($scope, element, attrs) {
93 | // don't need to do anything here.
94 | }
95 | }
96 | });
97 |
--------------------------------------------------------------------------------
/Lesson06/filters_directives/front/app/controllers/albumlistcontroller.js:
--------------------------------------------------------------------------------
1 | (function() {
2 |
3 | function AlbumListController ($scope, albumProvider, $location) {
4 |
5 | $scope.new_album = {};
6 | $scope.add_error_text = '';
7 | $scope.page_load_error = "";
8 |
9 | albumProvider.getAlbums(function (err, albums) {
10 | if (err) {
11 | $scope.page_load_error = "Unexpected error loading albums: " + e.message;
12 | } else {
13 | $scope.albums = albums;
14 | }
15 | });
16 |
17 | $scope.addAlbum = function (album_data) {
18 |
19 | albumProvider.addAlbum(album_data, function (err, results) {
20 | if (err) {
21 | if (err.code == "missing_title")
22 | $scope.add_error_text = "Missing title";
23 | else if (err.code == "bad_date")
24 | $scope.add_error_text = "You must specify a date (yyyy/mm/dd)";
25 | else if (err.code == "missing_description")
26 | $scope.add_error_text = "Missing description";
27 | else if (err.code == "bad_name")
28 | $scope.add_error_text = "Short album name must be at least 6 chars (ironic, yes)";
29 | } else {
30 | // looks good!
31 | $scope.new_album = {};
32 | $scope.add_error_text = '';
33 |
34 | // now, redirect to load in the album!
35 | $location.path("/album/" + album_data.name);
36 | }
37 |
38 | });
39 | };
40 | }
41 |
42 | photoApp.controller("AlbumListController", AlbumListController);
43 |
44 | })();
45 |
--------------------------------------------------------------------------------
/Lesson06/filters_directives/front/app/controllers/albumuploadcontroller.js:
--------------------------------------------------------------------------------
1 | (function () {
2 |
3 | function AlbumUploadController ($scope, $location, $routeParams, albumProvider) {
4 | $scope.album_name = $routeParams.album_name;
5 | $scope.page_load_error = "";
6 | $scope.done_uploading = false;
7 |
8 | // ADD FIRST!
9 | albumProvider.getAlbumByName($scope.album_name, function (err, photos) {
10 | if (err) {
11 | if (err.error == "not_found")
12 | $scope.page_load_error = "No such album. Are you calling this right?";
13 | else
14 | $scope.page_load_error = "Unexpected error loading albums: " + err.message;
15 | } else {
16 | $scope.photos = photos;
17 | }
18 | });
19 |
20 | $scope.uploader = albumProvider.getUploader($scope.album_name, $scope);
21 |
22 |
23 |
24 | $scope.uploader.bind("completeall", function (event, items) {
25 | $scope.done_uploading = true;
26 | });
27 |
28 |
29 | $scope.uploadFiles = function () {
30 | $scope.uploader.uploadAll();
31 | }
32 |
33 |
34 |
35 | // FOR DESCRIPTIONS
36 | $scope.descriptions = {};
37 | $scope.uploader.bind('beforeupload', function (event, item) {
38 | var fn = item.file.name;
39 | var d = item.file.lastModifiedDate;
40 | item.formData = [{
41 | filename: _fix_filename(item.file.name),
42 | description: $scope.descriptions[item.file.name],
43 | date: d.getFullYear() + "/" + d.getMonth() + "/" + d.getDate()
44 | } ];
45 | });
46 |
47 |
48 | }
49 |
50 | photoApp.controller("AlbumUploadController", AlbumUploadController);
51 |
52 |
53 | /**
54 | * we'll be super fussy and only allow alnum, -, _, and .
55 | */
56 | function _fix_filename(fn) {
57 | if (!fn || fn.length == 0) return "unknown";
58 |
59 | var r = new RegExp("^[a-zA-Z0-9\\-_.]+$");
60 | var out = "";
61 |
62 | for (var i = 0; i < fn.length; i++) {
63 | if (r.exec(fn[i]) != null)
64 | out += fn[i];
65 | }
66 |
67 | if (!out) out = "unknown_" + (new Date()).getTime();
68 | return out;
69 | }
70 |
71 |
72 |
73 | })();
74 |
--------------------------------------------------------------------------------
/Lesson06/filters_directives/front/app/controllers/albumviewercontroller.js:
--------------------------------------------------------------------------------
1 | (function() {
2 |
3 | function AlbumViewerController ($scope, $location, $routeParams, albumProvider) {
4 | $scope.album_name = $routeParams.album_name;
5 | $scope.page_load_error = "";
6 |
7 | albumProvider.getAlbumByName($scope.album_name, function (err, photos) {
8 | if (err) {
9 | if (err.error == "not_found")
10 | $scope.page_load_error = "No such album. Are you calling this right?";
11 | else
12 | $scope.page_load_error = "Unexpected error loading albums: " + err.message;
13 | } else {
14 | $scope.photos = photos;
15 | }
16 | });
17 | }
18 |
19 | photoApp.controller("AlbumViewerController", AlbumViewerController);
20 |
21 | })();
22 |
--------------------------------------------------------------------------------
/Lesson06/filters_directives/front/app/controllers/photoviewercontroller.js:
--------------------------------------------------------------------------------
1 | (function() {
2 |
3 | // what about date and description???
4 | // for next lesson!!!
5 | function PhotoViewerController ($scope, $routeParams) {
6 | $scope.album_name = $routeParams.album_name;
7 | $scope.photo_filename = $routeParams.photo_filename;
8 | }
9 |
10 |
11 | photoApp.controller("PhotoViewerController", PhotoViewerController);
12 |
13 | })();
14 |
--------------------------------------------------------------------------------
/Lesson06/filters_directives/front/app/partials/album_list.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | {{page_load_error}}
4 |
5 |
6 | HELLO THERE
7 |
8 | Displaying {{ albums.length | pluralise:{one:"city", more:"cities"} }}
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
23 |
24 | {{ album.description }}
25 |
26 |
27 |
28 |
29 |
30 | Add new album
31 |
32 |
{{add_error_text}}
33 |
34 |
41 |
42 |
43 |
44 |
45 |
46 |
53 |
54 |
Add New Album
55 |
56 |
57 |
58 |
--------------------------------------------------------------------------------
/Lesson06/filters_directives/front/app/partials/album_uploader.html:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 | {{page_load_error}}
7 |
8 |
9 |
10 |
11 |
12 |
13 |
Name: {{ item.file.name }}
14 |
Size: {{ item.file.size/1024/1024|number:2 }} Mb
15 |
16 | Description:
17 |
18 |
19 |
20 |
21 | Upload Progress: {{ item.progress }}
22 |
25 |
26 |
27 |
28 | Remove
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 | Total progress: {{ uploader.progress }}
37 |
40 |
41 |
Upload all
42 |
Cancel all
43 |
Remove all
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
58 |
--------------------------------------------------------------------------------
/Lesson06/filters_directives/front/app/partials/album_viewer.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | {{page_load_error}}
4 |
5 | {{album_name}}
6 |
7 |
8 |
9 |
10 |
11 |
12 |
{{ photo.description }}
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 | Add files to this album
21 |
22 |
--------------------------------------------------------------------------------
/Lesson06/filters_directives/front/app/partials/photo_viewer.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {{album_name}}
6 |
7 |
8 |
9 |
10 |
11 |
12 | I'd like to have the description here.
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/Lesson06/filters_directives/front/app/services/albumprovider.js:
--------------------------------------------------------------------------------
1 | (function () {
2 |
3 | function albumProvider ($http, $fileUploader) {
4 |
5 | this.getUploader = function (album_name, scope) {
6 | // create a uploader with options
7 | return $fileUploader.create({
8 | scope: scope,
9 | method: "PUT",
10 | url: "/v1/albums/" + album_name + "/photos.json"
11 | });
12 | };
13 |
14 | this.getAlbums = function (callback) {
15 | $http.get("/v1/albums.json")
16 | .success(function (data, status, headers, conf) {
17 | callback(null, data);
18 | })
19 | .error(function (data, status, headers, conf) {
20 | // just send back the error
21 | callback(data);
22 | });
23 | };
24 |
25 | this.addAlbum = function (album_data, callback) {
26 |
27 | if (!album_data.title) throw new Error("missing_title");
28 | if (!album_data.description) throw new Error("missing_description");
29 | if (!album_data.date) throw new Error("bad_date");
30 |
31 | var d = new Date(album_data.date.trim());
32 | if (isNaN(d.getTime())) throw new Error("bad_date");
33 |
34 | $http.put("/v1/albums.json", album_data)
35 | .success(function (data, status, headers, conf) {
36 | callback(null, data);
37 | })
38 | .error(function (data, status, headers, conf) {
39 | // just send back the error
40 | callback(data);
41 | });
42 | };
43 |
44 |
45 | this.getAlbumByName = function (name, callback) {
46 | $http.get("/v1/albums/" + name + "/photos.json")
47 | .success(function (data, status, headers, conf) {
48 | callback(null, data);
49 | })
50 | .error(function (data, status, headers, conf) {
51 | // just send back the error
52 | callback(data);
53 | });
54 | };
55 | }
56 |
57 | photoApp.service("albumProvider", albumProvider);
58 |
59 | })();
60 |
--------------------------------------------------------------------------------
/Lesson06/filters_directives/front/app/services/configprops.js:
--------------------------------------------------------------------------------
1 | (function () {
2 |
3 | photoApp.constant("appConfigurationProps", {
4 | json_server_host: "localhost",
5 | json_server_port: 8082
6 | });
7 |
8 | })();
9 |
--------------------------------------------------------------------------------
/Lesson06/filters_directives/front/css/app.css:
--------------------------------------------------------------------------------
1 | body {
2 | padding: 50px;
3 | }
4 |
5 | input[type=text] {
6 | padding: 3px;
7 | border-radius: 5px;
8 | border: 1px solid #bbb;
9 | }
10 |
11 | .error {
12 | color: #a00;
13 | }
14 |
15 | textarea {
16 | padding: 3px;
17 | border-radius: 5px;
18 | border: 1px solid #bbb;
19 | }
20 |
21 | .album {
22 | width: 300px;
23 | float: left;
24 | margin-right: 10px;
25 | }
26 |
27 | div.album div.title {
28 | float: right;
29 | }
30 |
31 |
32 | div.album .panel-heading a {
33 | text-decoration: none;
34 | color: white;
35 | }
36 | div.album .panel-heading a:hover {
37 | text-decoration: underline;
38 | color: white;
39 | }
--------------------------------------------------------------------------------
/Lesson06/filters_directives/front/fonts/glyphicons-halflings-regular.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcwan/AngularJSLiveLessons/cef58c015affd54f775a5415d81fa4799aa76f1e/Lesson06/filters_directives/front/fonts/glyphicons-halflings-regular.eot
--------------------------------------------------------------------------------
/Lesson06/filters_directives/front/fonts/glyphicons-halflings-regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcwan/AngularJSLiveLessons/cef58c015affd54f775a5415d81fa4799aa76f1e/Lesson06/filters_directives/front/fonts/glyphicons-halflings-regular.ttf
--------------------------------------------------------------------------------
/Lesson06/filters_directives/front/fonts/glyphicons-halflings-regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcwan/AngularJSLiveLessons/cef58c015affd54f775a5415d81fa4799aa76f1e/Lesson06/filters_directives/front/fonts/glyphicons-halflings-regular.woff
--------------------------------------------------------------------------------
/Lesson06/filters_directives/front/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/Lesson07/01_cleaning_up/README.md:
--------------------------------------------------------------------------------
1 | NodePhotoServer
2 | ===============
3 |
4 | ## Installation instructions
5 |
6 | This server assumes you have Node 0.10.x installed somewhere on your computer and in your path. To install, just download the source for this tree or clone it somewhere on your local hard drive and then copy your AngularJS application to the front/ folder within it.
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Lesson07/01_cleaning_up/back/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "photo_server",
3 | "description": "Simple Demo backend for our photo server.",
4 | "private": true,
5 | "dependencies": {
6 | "async": "0.2.x",
7 | "express": "3.x"
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/Lesson07/01_cleaning_up/back/photo_albums.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "name": "asdfasfd",
4 | "title": "asdf",
5 | "date": "2222/2/2",
6 | "description": "asdfasdf",
7 | "photos": [
8 | {
9 | "filename": "IMG_20140420_144009.jpg",
10 | "date": "2014/3/20",
11 | "description": "nice"
12 | },
13 | {
14 | "filename": "IMG_20140420_144013.jpg",
15 | "date": "2014/3/20",
16 | "description": "woo"
17 | },
18 | {
19 | "filename": "IMG_20140420_144029.jpg",
20 | "date": "2014/3/20",
21 | "description": "fun"
22 | },
23 | {
24 | "filename": "IMG_20140420_144034.jpg",
25 | "date": "2014/3/20",
26 | "description": "awesome"
27 | },
28 | {
29 | "filename": "IMG_20140420_154149.jpg",
30 | "date": "2014/3/20",
31 | "description": "asdfasdf"
32 | },
33 | {
34 | "filename": "IMG_20140420_154247.jpg",
35 | "date": "2014/3/20",
36 | "description": "dijpasdofij"
37 | },
38 | {
39 | "filename": "IMG_20140419_164913.jpg",
40 | "date": "2014/3/19",
41 | "description": "d1"
42 | },
43 | {
44 | "filename": "IMG_20140419_164918.jpg",
45 | "date": "2014/3/19",
46 | "description": "d2"
47 | },
48 | {
49 | "filename": "IMG_20140419_165222.jpg",
50 | "date": "2014/3/19",
51 | "description": "d3"
52 | },
53 | {
54 | "filename": "IMG_20140419_165227.jpg",
55 | "date": "2014/3/19",
56 | "description": "d4"
57 | },
58 | {
59 | "filename": "IMG_20140419_165746.jpg",
60 | "date": "2014/3/19",
61 | "description": "d5"
62 | },
63 | {
64 | "filename": "IMG_20140419_165750.jpg",
65 | "date": "2014/3/19",
66 | "description": "d6"
67 | },
68 | {
69 | "filename": "IMG_20140419_165754.jpg",
70 | "date": "2014/3/19",
71 | "description": "d7"
72 | },
73 | {
74 | "filename": "IMG_20140419_170230.jpg",
75 | "date": "2014/3/19",
76 | "description": "d8"
77 | },
78 | {
79 | "filename": "IMG_20130319_140649.jpg",
80 | "date": "2013/2/19",
81 | "description": "undefined"
82 | },
83 | {
84 | "filename": "IMG_20130319_154722.jpg",
85 | "date": "2013/2/19",
86 | "description": "undefined"
87 | },
88 | {
89 | "filename": "IMG_20130319_154829.jpg",
90 | "date": "2013/2/19",
91 | "description": "undefined"
92 | },
93 | {
94 | "filename": "IMG_20130319_163227.jpg",
95 | "date": "2013/2/19",
96 | "description": "undefined"
97 | },
98 | {
99 | "filename": "IMG_20130319_163229.jpg",
100 | "date": "2013/2/19",
101 | "description": "undefined"
102 | },
103 | {
104 | "filename": "IMG_20130319_163234.jpg",
105 | "date": "2013/2/19",
106 | "description": "undefined"
107 | }
108 | ]
109 | },
110 | {
111 | "name": "asdfasdf",
112 | "title": "sadfasdfasdf",
113 | "date": "2014/01/01",
114 | "description": "asodfipjas dofijas pdfoijas dfpoiasdjf apsoid",
115 | "photos": []
116 | },
117 | {
118 | "name": "qwerqwerqwre",
119 | "title": "qwerty",
120 | "date": "2014/1/2",
121 | "description": "asdofijp asdofija spdfoiasj f",
122 | "photos": []
123 | },
124 | {
125 | "name": "zxcvzxcvzxcv",
126 | "title": "zxcvzxcv",
127 | "date": "2013/3/3",
128 | "description": "asivpjoidjfaspdo fij",
129 | "photos": []
130 | },
131 | {
132 | "name": "fishyfish",
133 | "title": "fish",
134 | "date": "2013/4/5",
135 | "description": "asdfsf",
136 | "photos": []
137 | },
138 | {
139 | "name": "dogcatfish",
140 | "title": "dog cat",
141 | "date": "2012/3/5",
142 | "description": "asdiofjpasfoi",
143 | "photos": []
144 | }
145 | ]
--------------------------------------------------------------------------------
/Lesson07/01_cleaning_up/front/app/controllers/albumlistcontroller.js:
--------------------------------------------------------------------------------
1 | (function () {
2 |
3 | function AlbumListController ($scope, $location, albumProvider, $modal) {
4 | $scope.page_load_error = "";
5 | $scope.done_loading = false;
6 |
7 | albumProvider.getAlbums(function (err, albums) {
8 | if (err) {
9 | $scope.page_load_error = "Unexpected error loading albums: " + err.message;
10 | } else {
11 | $scope.done_loading = true;
12 | $scope.albums = albums;
13 | }
14 | });
15 |
16 | $scope.openAddAlbumDialog = function () {
17 | var addAlbumDialog = $modal.open({
18 | size: "sm",
19 | templateUrl: 'myModalContent.html',
20 | controller: AddAlbumDialogController,
21 | resolve: {
22 | }
23 | });
24 |
25 | addAlbumDialog.result.then(function (album_name) {
26 | $location.path("/album/" + album_name)
27 | }, function () {
28 | console.info('Modal dismissed at: ' + new Date());
29 | });
30 | };
31 | }
32 |
33 | photoApp.controller("AlbumListController", AlbumListController);
34 |
35 |
36 |
37 | function AddAlbumDialogController ($scope, $location, $modalInstance, albumProvider) {
38 | $scope.add_album_error = "";
39 | $scope.adding_album = {};
40 |
41 | $scope.addAlbum = function (new_album) {
42 | albumProvider.addAlbum(new_album, function (err, album) {
43 | if (err) {
44 | if (err.code == "missing_title")
45 | $scope.add_album_error = "You need to give a title";
46 | else if (err.code == "missing_description")
47 | $scope.add_album_error = "You need to give a description";
48 | else if (err.code == "missing_date")
49 | $scope.add_album_error = "You need to give a date";
50 | else if (err.code == "missing_name")
51 | $scope.add_album_error = "You need to give a name";
52 | else if (err.code == "bad_date")
53 | $scope.add_album_error = "That doesn't look like a good date.";
54 | else if (err.code == "duplicate_album_name")
55 | $scope.add_album_error = "An album of that name already exists!";
56 | else
57 | $scope.add_album_error = "A completely unexpected error occurred: " + err.code + " " + err.message;
58 | } else {
59 | $modalInstance.close($scope.adding_album.name);
60 | }
61 | });
62 | };
63 |
64 |
65 |
66 | $scope.ok = function () {
67 | $scope.addAlbum($scope.adding_album);
68 | };
69 |
70 | $scope.cancel = function () {
71 | $modalInstance.dismiss('cancel');
72 | };
73 | };
74 |
75 | photoApp.controller("AddAlbumDialogController", AddAlbumDialogController);
76 |
77 |
78 | })();
79 |
--------------------------------------------------------------------------------
/Lesson07/01_cleaning_up/front/app/controllers/albumuploadcontroller.js:
--------------------------------------------------------------------------------
1 | (function () {
2 |
3 |
4 | function AlbumUploadController ($scope, $routeParams, albumProvider) {
5 | $scope.album_name = $routeParams.album_name;
6 | $scope.page_load_error = "";
7 | $scope.descriptions = {};
8 |
9 | albumProvider.getPhotosForAlbum($scope.album_name, function (err, photos) {
10 | if (err) {
11 | if (err.code == "not_found")
12 | $scope.page_load_error = "No such album. Are you doing this right?";
13 | else
14 | $scope.page_load_error = "Unexpected error loading page: " + err.code + " " + err.message;
15 | } else {
16 | $scope.photos = photos;
17 | $scope.uploader = albumProvider.getUploader($scope.album_name, $scope);
18 |
19 | $scope.uploader.bind("completeall", function (event, items) {
20 | $scope.done_uploading = true;
21 | albumProvider.albumChanged($scope.album_name);
22 | });
23 |
24 |
25 | $scope.uploader.bind("beforeupload", function (event, item) {
26 | var fn = _fix_filename(item.file.name);
27 | var d = item.file.lastModifiedDate;
28 | var dstr = d.getFullYear() + "/" + d.getMonth() + "/" + d.getDate();
29 |
30 | item.formData = [{
31 | filename: fn,
32 | date: dstr ? dstr : "",
33 | description: $scope.descriptions[item.file.name]
34 | }];
35 | });
36 | }
37 | });
38 |
39 | }
40 |
41 | photoApp.controller("AlbumUploadController", AlbumUploadController);
42 |
43 |
44 |
45 | /**
46 | * we'll be super fussy and only allow alnum, -, _, and .
47 | */
48 | function _fix_filename(fn) {
49 | if (!fn || fn.length == 0) return "unknown";
50 |
51 | var r = new RegExp("^[a-zA-Z0-9\\-_.]+$");
52 | var out = "";
53 |
54 | for (var i = 0; i < fn.length; i++) {
55 | if (r.exec(fn[i]) != null)
56 | out += fn[i];
57 | }
58 |
59 | if (!out) out = "unknown_" + (new Date()).getTime();
60 | return out;
61 | }
62 |
63 |
64 |
65 |
66 |
67 | })();
68 |
--------------------------------------------------------------------------------
/Lesson07/01_cleaning_up/front/app/controllers/albumviewcontroller.js:
--------------------------------------------------------------------------------
1 | (function () {
2 |
3 |
4 | function AlbumViewController ($scope, $routeParams, albumProvider) {
5 | $scope.load_error_text = "";
6 | $scope.album_name = $routeParams.album_name;
7 | $scope.page_load_error = "";
8 | $scope.album = null;
9 |
10 | albumProvider.getAlbum($scope.album_name, function (err, album) {
11 | if (err) {
12 | if (err.code == "not_found")
13 | $scope.page_load_error = "No such album. Are you doing this right?";
14 | else
15 | $scope.page_load_error = "Unexpected error loading page: " + err.code + " " + err.message;
16 | } else {
17 | $scope.album = album;
18 | }
19 | });
20 |
21 | }
22 |
23 |
24 | photoApp.controller("AlbumViewController", AlbumViewController);
25 |
26 | })();
27 |
--------------------------------------------------------------------------------
/Lesson07/01_cleaning_up/front/app/controllers/photoviewcontroller.js:
--------------------------------------------------------------------------------
1 | (function () {
2 |
3 | function PhotoViewController ($scope, $routeParams, albumProvider, $location, $rootScope) {
4 | $scope.album_name = $routeParams.album_name;
5 | $scope.page_load_error = "";
6 | $scope.album = null;
7 | $scope.photo_filename = $routeParams.filename;
8 | $scope.photo_next_file = '';
9 | $scope.photo_prev_file = '';
10 | $scope.done_loading = false;
11 | $scope.description = '';
12 |
13 | $rootScope.$on("keypress:39", function (e, ke) {
14 | if ($scope.photo_next_file) {
15 | setTimeout(function () {
16 | $scope.$apply(function () {$location.path("/album/" + $scope.album_name + "/photo/" + $scope.photo_next_file); });
17 | }, 200);
18 | };
19 | });
20 |
21 | $rootScope.$on("keypress:37", function (e, ke) {
22 | if ($scope.photo_prev_file) {
23 | setTimeout(function () {
24 | $scope.$apply(function () {$location.path("/album/" + $scope.album_name + "/photo/" + $scope.photo_prev_file); });
25 | }, 200);
26 | }
27 | });
28 |
29 | albumProvider.getAlbum($scope.album_name, function (err, album) {
30 | if (err) {
31 | if (err.code == "not_found")
32 | $scope.page_load_error = "No such album. Are you doing this right?";
33 | else
34 | $scope.page_load_error = "Unexpected error loading page: " + err.code + " " + err.message;
35 | } else {
36 | $scope.album = album;
37 | for (var i = 0; i < album.photos.length; i++) {
38 | if (album.photos[i].filename == $scope.photo_filename) {
39 | $scope.description = album.photos[i].description;
40 | if (i) $scope.photo_prev_file = album.photos[i -1].filename;
41 | if (i < album.photos.length - 1)
42 | $scope.photo_next_file = album.photos[i + 1].filename;
43 | break;
44 | }
45 | }
46 |
47 | if (i == album.photos.length)
48 | $scope.page_load_error = "This photo does not appear to exist.";
49 | else
50 | $scope.done_loading = true;
51 | }
52 | });
53 |
54 | }
55 |
56 |
57 | photoApp.controller("PhotoViewController", PhotoViewController);
58 |
59 | })();
60 |
--------------------------------------------------------------------------------
/Lesson07/01_cleaning_up/front/app/partials/.#album_uploader.html:
--------------------------------------------------------------------------------
1 | livelessons@Kimidori.local.7430
--------------------------------------------------------------------------------
/Lesson07/01_cleaning_up/front/app/partials/album_list_partial.html:
--------------------------------------------------------------------------------
1 |
2 | {{ page_load_error }}
3 |
4 | Loading page data ....
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | Displaying {{ albums.length | pluralise:{ sing: "album", plur: "albums"} }}:
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
51 |
52 |
53 |
Create New Album
54 |
55 |
56 |
--------------------------------------------------------------------------------
/Lesson07/01_cleaning_up/front/app/partials/album_uploader.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
{{page_load_error}}
5 |
6 |
7 |
8 |
9 |
10 |
11 |
13 |
Name: {{ item.file.name }}
14 |
Size: {{ item.file.size/1024/1024|number:2 }} Mb
15 |
16 |
17 |
Description:
18 |
19 |
20 |
21 |
22 | Upload Progress: {{ item.progress }}
23 |
26 |
27 |
28 |
29 | Remove
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 | Total progress: {{ uploader.progress }}
38 |
41 |
42 |
Upload all
43 |
Cancel all
44 |
Remove all
45 |
46 |
47 |
48 |
53 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/Lesson07/01_cleaning_up/front/app/partials/album_view_partial.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
9 |
10 |
{{ page_load_error }}
11 |
12 |
{{ album.title }} ({{ album.name }})
13 |
14 |
{{ load_error_text }}
15 |
16 |
17 |
18 | {{ album.description }}
19 |
20 |
21 |
22 |
23 |
28 |
29 | {{ photo.description }}
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 | Add files to this album
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/Lesson07/01_cleaning_up/front/app/partials/pa-album-directive.html:
--------------------------------------------------------------------------------
1 |
2 |
7 |
{{ albumdata.description }}
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/Lesson07/01_cleaning_up/front/app/partials/photo_view.html:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
10 | {{ load_error_text }}
11 |
12 |
13 |
14 | Loading ...
15 |
16 |
17 |
20 |
21 |
22 |
25 |
28 |
29 |
30 |
31 |
32 |
33 | {{ description }}
34 | This is something a wee bit longer that I hope will wrap and show me the correc tpath to enlightenment. Only through fire shall our sins be cleansed.
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/Lesson07/01_cleaning_up/front/app/services/albumservice.js:
--------------------------------------------------------------------------------
1 | (function () {
2 |
3 | function albumProvider ($http, $fileUploader) {
4 |
5 | var album_cache = {};
6 |
7 | this.getUploader = function (album_name, scope) {
8 | return $fileUploader.create({
9 | scope: scope,
10 | method: "PUT",
11 | url: "/v1/albums/" + album_name + "/photos.json"
12 | });
13 | };
14 |
15 | this.albumChanged = function (name) {
16 | if (album_cache[name]) delete album_cache[name];
17 | };
18 |
19 | this.getAlbums = function (callback) {
20 | $http.get("/v1/albums.json")
21 | .success(function (data, status, headers, conf) {
22 | callback(null, data);
23 | })
24 | .error(function (data, status, headers, conf) {
25 | callback(data);
26 | });
27 | };
28 |
29 | this.getAlbum = function (name, callback) {
30 | if (album_cache[name]) return callback(null, album_cache[name]);
31 |
32 | $http.get("/v1/albums/" + name + ".json")
33 | .success(function (data, status, headers, conf) {
34 | album_cache[name] = data;
35 | callback(null, data);
36 | })
37 | .error(function (data, status, headers, conf) {
38 | callback(data);
39 | });
40 | };
41 |
42 | this.getPhotosForAlbum = function (name, callback) {
43 | if (album_cache[name]) return callback(null, album_cache[name].photos);
44 |
45 | $http.get("/v1/albums/" + name + "/photos.json")
46 | .success(function (data, status, headers, conf) {
47 | album_cache[name] = data;
48 | callback(null, data);
49 | })
50 | .error(function (data, status, headers, conf) {
51 | callback(data);
52 | });
53 | };
54 |
55 |
56 | this.addAlbum = function (album_data, callback) {
57 |
58 | if (!album_data.name) return callback({ code: "missing_name" });
59 | if (!album_data.title) return callback({ code: "missing_title" });
60 | if (!album_data.description) return callback({ code: "missing_description" });
61 | if (!album_data.date) return callback({ code: "missing_date" });
62 | if (!is_valid_date(album_data.date)) return callback({ code: "bad_date" });
63 |
64 | $http.put("/v1/albums.json", album_data)
65 | .success(function (data, status, headers, conf) {
66 | callback(null, data);
67 | })
68 | .error(function (data, status, headers, conf) {
69 | callback(data);
70 | });
71 | };
72 | }
73 |
74 | photoApp.service("albumProvider", albumProvider);
75 |
76 |
77 |
78 |
79 |
80 | function is_valid_date(the_date) {
81 | if (the_date.match(/^[0-9]{2,4}[\-\/\. ,][0-9]{1,2}[\-\/\. ,][0-9]{1,2}$/)) {
82 | var d = new Date(the_date);
83 | return !isNaN(d.getTime());
84 | } else {
85 | return false;
86 | }
87 | }
88 |
89 |
90 |
91 | })();
92 |
--------------------------------------------------------------------------------
/Lesson07/01_cleaning_up/front/css/app.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | padding: 0;
4 | }
5 |
6 | div#top_bar {
7 | text-align: left;
8 | background-color: #f2f2f2;
9 | border-bottom: 1px solid #ddd;
10 | height: 60px;
11 | }
12 |
13 |
14 | div#top_bar a {
15 | text-decoration: none;
16 | }
17 | div#top_bar .glyphicon {
18 | float: left;
19 | font-size: 400%;
20 | padding-left: 20px;
21 | padding-bottom: 10px;
22 | padding-top: 3px;
23 | padding-right: 20px;
24 | color: #666;
25 | }
26 |
27 | div#top_bar div#title {
28 | border-left: 1px solid #ccc;
29 | font-family: Helvetica;
30 | font-size: 28px;
31 | height: 60px;
32 | padding-left: 10px;
33 | margin-left: 95px;
34 | padding-top: 12px;
35 | font-weight: 100;
36 | color: #666;
37 | }
38 |
39 |
40 | input[type=text] {
41 | padding: 3px;
42 | border-radius: 4px;
43 | border: 1px solid #bbb;
44 | }
45 |
46 | textarea {
47 | padding: 3px;
48 | border-radius: 4px;
49 | border: 1px solid #bbb;
50 | }
51 |
52 |
53 | div.album {
54 | float: left;
55 | width: 300px;
56 | margin-right: 10px;
57 | min-height: 200px;
58 | }
59 |
60 | div.album div.description {
61 | padding: 5px;
62 | }
63 |
64 | div.album div.panel-heading a {
65 | color: white;
66 | }
--------------------------------------------------------------------------------
/Lesson07/01_cleaning_up/front/fonts/glyphicons-halflings-regular.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcwan/AngularJSLiveLessons/cef58c015affd54f775a5415d81fa4799aa76f1e/Lesson07/01_cleaning_up/front/fonts/glyphicons-halflings-regular.eot
--------------------------------------------------------------------------------
/Lesson07/01_cleaning_up/front/fonts/glyphicons-halflings-regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcwan/AngularJSLiveLessons/cef58c015affd54f775a5415d81fa4799aa76f1e/Lesson07/01_cleaning_up/front/fonts/glyphicons-halflings-regular.ttf
--------------------------------------------------------------------------------
/Lesson07/01_cleaning_up/front/fonts/glyphicons-halflings-regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcwan/AngularJSLiveLessons/cef58c015affd54f775a5415d81fa4799aa76f1e/Lesson07/01_cleaning_up/front/fonts/glyphicons-halflings-regular.woff
--------------------------------------------------------------------------------
/Lesson07/01_cleaning_up/front/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
My Photo Albums
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/Lesson07/01_cleaning_up/front/js/angular-route.min.js:
--------------------------------------------------------------------------------
1 | /*
2 | AngularJS v1.2.16
3 | (c) 2010-2014 Google, Inc. http://angularjs.org
4 | License: MIT
5 | */
6 | (function(n,e,A){'use strict';function x(s,g,k){return{restrict:"ECA",terminal:!0,priority:400,transclude:"element",link:function(a,c,b,f,w){function y(){p&&(p.remove(),p=null);h&&(h.$destroy(),h=null);l&&(k.leave(l,function(){p=null}),p=l,l=null)}function v(){var b=s.current&&s.current.locals;if(e.isDefined(b&&b.$template)){var b=a.$new(),d=s.current;l=w(b,function(d){k.enter(d,null,l||c,function(){!e.isDefined(t)||t&&!a.$eval(t)||g()});y()});h=d.scope=b;h.$emit("$viewContentLoaded");h.$eval(u)}else y()}
7 | var h,l,p,t=b.autoscroll,u=b.onload||"";a.$on("$routeChangeSuccess",v);v()}}}function z(e,g,k){return{restrict:"ECA",priority:-400,link:function(a,c){var b=k.current,f=b.locals;c.html(f.$template);var w=e(c.contents());b.controller&&(f.$scope=a,f=g(b.controller,f),b.controllerAs&&(a[b.controllerAs]=f),c.data("$ngControllerController",f),c.children().data("$ngControllerController",f));w(a)}}}n=e.module("ngRoute",["ng"]).provider("$route",function(){function s(a,c){return e.extend(new (e.extend(function(){},
8 | {prototype:a})),c)}function g(a,e){var b=e.caseInsensitiveMatch,f={originalPath:a,regexp:a},k=f.keys=[];a=a.replace(/([().])/g,"\\$1").replace(/(\/)?:(\w+)([\?\*])?/g,function(a,e,b,c){a="?"===c?c:null;c="*"===c?c:null;k.push({name:b,optional:!!a});e=e||"";return""+(a?"":e)+"(?:"+(a?e:"")+(c&&"(.+?)"||"([^/]+)")+(a||"")+")"+(a||"")}).replace(/([\/$\*])/g,"\\$1");f.regexp=RegExp("^"+a+"$",b?"i":"");return f}var k={};this.when=function(a,c){k[a]=e.extend({reloadOnSearch:!0},c,a&&g(a,c));if(a){var b=
9 | "/"==a[a.length-1]?a.substr(0,a.length-1):a+"/";k[b]=e.extend({redirectTo:a},g(b,c))}return this};this.otherwise=function(a){this.when(null,a);return this};this.$get=["$rootScope","$location","$routeParams","$q","$injector","$http","$templateCache","$sce",function(a,c,b,f,g,n,v,h){function l(){var d=p(),m=r.current;if(d&&m&&d.$$route===m.$$route&&e.equals(d.pathParams,m.pathParams)&&!d.reloadOnSearch&&!u)m.params=d.params,e.copy(m.params,b),a.$broadcast("$routeUpdate",m);else if(d||m)u=!1,a.$broadcast("$routeChangeStart",
10 | d,m),(r.current=d)&&d.redirectTo&&(e.isString(d.redirectTo)?c.path(t(d.redirectTo,d.params)).search(d.params).replace():c.url(d.redirectTo(d.pathParams,c.path(),c.search())).replace()),f.when(d).then(function(){if(d){var a=e.extend({},d.resolve),c,b;e.forEach(a,function(d,c){a[c]=e.isString(d)?g.get(d):g.invoke(d)});e.isDefined(c=d.template)?e.isFunction(c)&&(c=c(d.params)):e.isDefined(b=d.templateUrl)&&(e.isFunction(b)&&(b=b(d.params)),b=h.getTrustedResourceUrl(b),e.isDefined(b)&&(d.loadedTemplateUrl=
11 | b,c=n.get(b,{cache:v}).then(function(a){return a.data})));e.isDefined(c)&&(a.$template=c);return f.all(a)}}).then(function(c){d==r.current&&(d&&(d.locals=c,e.copy(d.params,b)),a.$broadcast("$routeChangeSuccess",d,m))},function(c){d==r.current&&a.$broadcast("$routeChangeError",d,m,c)})}function p(){var a,b;e.forEach(k,function(f,k){var q;if(q=!b){var g=c.path();q=f.keys;var l={};if(f.regexp)if(g=f.regexp.exec(g)){for(var h=1,p=g.length;h !!!!",
110 | transclude: true,
111 | link: function ($scope, element, attrs) {
112 | element.css({
113 | "background-color": "yellow",
114 | color: "red",
115 | padding: "10px",
116 | "font-weight": "bold"
117 | });
118 | }
119 | };
120 | });
121 |
122 |
123 |
124 | photoApp.directive("paAlbum", function () {
125 | return {
126 | restrict: "AE",
127 | scope: {
128 | albumdata: "="
129 | },
130 | templateUrl: "/app/partials/pa-album-directive.html",
131 | link: function ($scope, element, attrs) {
132 | // do nothing
133 | }
134 | }
135 | });
136 |
137 |
--------------------------------------------------------------------------------
/Lesson07/02_testing/front/app/controllers/albumlistcontroller.js:
--------------------------------------------------------------------------------
1 | (function () {
2 |
3 | function AlbumListController ($scope, $location, albumProvider, $modal) {
4 | $scope.page_load_error = "";
5 | $scope.done_loading = false;
6 |
7 | albumProvider.getAlbums(function (err, albums) {
8 | if (err) {
9 | $scope.page_load_error = "Unexpected error loading albums: " + err.message;
10 | } else {
11 | $scope.done_loading = true;
12 | $scope.albums = albums;
13 | }
14 | });
15 |
16 | $scope.openAddAlbumDialog = function () {
17 | var addAlbumDialog = $modal.open({
18 | size: "sm",
19 | templateUrl: 'myModalContent.html',
20 | controller: AddAlbumDialogController,
21 | resolve: {
22 | }
23 | });
24 |
25 | addAlbumDialog.result.then(function (album_name) {
26 | $location.path("/album/" + album_name)
27 | }, function () {
28 | console.info('Modal dismissed at: ' + new Date());
29 | });
30 | };
31 | }
32 |
33 | photoApp.controller("AlbumListController", AlbumListController);
34 |
35 |
36 |
37 | function AddAlbumDialogController ($scope, $location, $modalInstance, albumProvider) {
38 | $scope.add_album_error = "";
39 | $scope.adding_album = {};
40 |
41 | $scope.addAlbum = function (new_album) {
42 | albumProvider.addAlbum(new_album, function (err, album) {
43 | if (err) {
44 | if (err.code == "missing_title")
45 | $scope.add_album_error = "You need to give a title";
46 | else if (err.code == "missing_description")
47 | $scope.add_album_error = "You need to give a description";
48 | else if (err.code == "missing_date")
49 | $scope.add_album_error = "You need to give a date";
50 | else if (err.code == "missing_name")
51 | $scope.add_album_error = "You need to give a name";
52 | else if (err.code == "bad_date")
53 | $scope.add_album_error = "That doesn't look like a good date.";
54 | else if (err.code == "duplicate_album_name")
55 | $scope.add_album_error = "An album of that name already exists!";
56 | else
57 | $scope.add_album_error = "A completely unexpected error occurred: " + err.code + " " + err.message;
58 | } else {
59 | $modalInstance.close($scope.adding_album.name);
60 | }
61 | });
62 | };
63 |
64 |
65 |
66 | $scope.ok = function () {
67 | $scope.addAlbum($scope.adding_album);
68 | };
69 |
70 | $scope.cancel = function () {
71 | $modalInstance.dismiss('cancel');
72 | };
73 | };
74 |
75 | photoApp.controller("AddAlbumDialogController", AddAlbumDialogController);
76 |
77 |
78 | })();
79 |
--------------------------------------------------------------------------------
/Lesson07/02_testing/front/app/controllers/albumuploadcontroller.js:
--------------------------------------------------------------------------------
1 | (function () {
2 |
3 |
4 | function AlbumUploadController ($scope, $routeParams, albumProvider) {
5 | $scope.album_name = $routeParams.album_name;
6 | $scope.page_load_error = "";
7 | $scope.descriptions = {};
8 |
9 | albumProvider.getPhotosForAlbum($scope.album_name, function (err, photos) {
10 | if (err) {
11 | if (err.code == "not_found")
12 | $scope.page_load_error = "No such album. Are you doing this right?";
13 | else
14 | $scope.page_load_error = "Unexpected error loading page: " + err.code + " " + err.message;
15 | } else {
16 | $scope.photos = photos;
17 | $scope.uploader = albumProvider.getUploader($scope.album_name, $scope);
18 |
19 | $scope.uploader.bind("completeall", function (event, items) {
20 | $scope.done_uploading = true;
21 | albumProvider.albumChanged($scope.album_name);
22 | });
23 |
24 |
25 | $scope.uploader.bind("beforeupload", function (event, item) {
26 | var fn = _fix_filename(item.file.name);
27 | var d = item.file.lastModifiedDate;
28 | var dstr = d.getFullYear() + "/" + d.getMonth() + "/" + d.getDate();
29 |
30 | item.formData = [{
31 | filename: fn,
32 | date: dstr ? dstr : "",
33 | description: $scope.descriptions[item.file.name]
34 | }];
35 | });
36 | }
37 | });
38 |
39 | }
40 |
41 | photoApp.controller("AlbumUploadController", AlbumUploadController);
42 |
43 |
44 |
45 | /**
46 | * we'll be super fussy and only allow alnum, -, _, and .
47 | */
48 | function _fix_filename(fn) {
49 | if (!fn || fn.length == 0) return "unknown";
50 |
51 | var r = new RegExp("^[a-zA-Z0-9\\-_.]+$");
52 | var out = "";
53 |
54 | for (var i = 0; i < fn.length; i++) {
55 | if (r.exec(fn[i]) != null)
56 | out += fn[i];
57 | }
58 |
59 | if (!out) out = "unknown_" + (new Date()).getTime();
60 | return out;
61 | }
62 |
63 |
64 |
65 |
66 |
67 | })();
68 |
--------------------------------------------------------------------------------
/Lesson07/02_testing/front/app/controllers/albumviewcontroller.js:
--------------------------------------------------------------------------------
1 | (function () {
2 |
3 |
4 | function AlbumViewController ($scope, $routeParams, albumProvider) {
5 | $scope.load_error_text = "";
6 | $scope.album_name = $routeParams.album_name;
7 | $scope.page_load_error = "";
8 | $scope.album = null;
9 |
10 | albumProvider.getAlbum($scope.album_name, function (err, album) {
11 | if (err) {
12 | if (err.code == "not_found")
13 | $scope.page_load_error = "No such album. Are you doing this right?";
14 | else
15 | $scope.page_load_error = "Unexpected error loading page: " + err.code + " " + err.message;
16 | } else {
17 | $scope.album = album;
18 | }
19 | });
20 |
21 | }
22 |
23 |
24 | photoApp.controller("AlbumViewController", AlbumViewController);
25 |
26 | })();
27 |
--------------------------------------------------------------------------------
/Lesson07/02_testing/front/app/controllers/photoviewcontroller.js:
--------------------------------------------------------------------------------
1 | (function () {
2 |
3 | function PhotoViewController ($scope, $routeParams, albumProvider, $location, $rootScope) {
4 | $scope.album_name = $routeParams.album_name;
5 | $scope.page_load_error = "";
6 | $scope.album = null;
7 | $scope.photo_filename = $routeParams.filename;
8 | $scope.photo_next_file = '';
9 | $scope.photo_prev_file = '';
10 | $scope.done_loading = false;
11 | $scope.description = '';
12 |
13 | $rootScope.$on("keypress:39", function (e, ke) {
14 | if ($scope.photo_next_file) {
15 | setTimeout(function () {
16 | $scope.$apply(function () {$location.path("/album/" + $scope.album_name + "/photo/" + $scope.photo_next_file); });
17 | }, 200);
18 | };
19 | });
20 |
21 | $rootScope.$on("keypress:37", function (e, ke) {
22 | if ($scope.photo_prev_file) {
23 | setTimeout(function () {
24 | $scope.$apply(function () {$location.path("/album/" + $scope.album_name + "/photo/" + $scope.photo_prev_file); });
25 | }, 200);
26 | }
27 | });
28 |
29 | albumProvider.getAlbum($scope.album_name, function (err, album) {
30 | if (err) {
31 | if (err.code == "not_found")
32 | $scope.page_load_error = "No such album. Are you doing this right?";
33 | else
34 | $scope.page_load_error = "Unexpected error loading page: " + err.code + " " + err.message;
35 | } else {
36 | $scope.album = album;
37 | for (var i = 0; i < album.photos.length; i++) {
38 | if (album.photos[i].filename == $scope.photo_filename) {
39 | $scope.description = album.photos[i].description;
40 | if (i) $scope.photo_prev_file = album.photos[i -1].filename;
41 | if (i < album.photos.length - 1)
42 | $scope.photo_next_file = album.photos[i + 1].filename;
43 | break;
44 | }
45 | }
46 |
47 | if (i == album.photos.length)
48 | $scope.page_load_error = "This photo does not appear to exist.";
49 | else
50 | $scope.done_loading = true;
51 | }
52 | });
53 |
54 | }
55 |
56 |
57 | photoApp.controller("PhotoViewController", PhotoViewController);
58 |
59 | })();
60 |
--------------------------------------------------------------------------------
/Lesson07/02_testing/front/app/partials/.#album_uploader.html:
--------------------------------------------------------------------------------
1 | livelessons@Kimidori.local.7430
--------------------------------------------------------------------------------
/Lesson07/02_testing/front/app/partials/album_list_partial.html:
--------------------------------------------------------------------------------
1 |
2 |
{{ page_load_error }}
3 |
4 | Loading page data ....
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | Displaying {{ albums.length | pluralise:{ sing: "album", plur: "albums"} }}:
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
51 |
52 |
53 |
Create New Album
54 |
55 |
56 |
--------------------------------------------------------------------------------
/Lesson07/02_testing/front/app/partials/album_uploader.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
{{page_load_error}}
5 |
6 |
7 |
8 |
9 |
10 |
11 |
13 |
Name: {{ item.file.name }}
14 |
Size: {{ item.file.size/1024/1024|number:2 }} Mb
15 |
16 |
17 |
Description:
18 |
19 |
20 |
21 |
22 | Upload Progress: {{ item.progress }}
23 |
26 |
27 |
28 |
29 | Remove
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 | Total progress: {{ uploader.progress }}
38 |
41 |
42 |
Upload all
43 |
Cancel all
44 |
Remove all
45 |
46 |
47 |
48 |
53 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/Lesson07/02_testing/front/app/partials/album_view_partial.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
9 |
10 |
{{ page_load_error }}
11 |
12 |
{{ album.title }} ({{ album.name }})
13 |
14 |
{{ load_error_text }}
15 |
16 |
17 |
18 | {{ album.description }}
19 |
20 |
21 |
22 |
23 |
28 |
29 | {{ photo.description }}
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 | Add files to this album
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/Lesson07/02_testing/front/app/partials/pa-album-directive.html:
--------------------------------------------------------------------------------
1 |
2 |
7 |
{{ albumdata.description }}
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/Lesson07/02_testing/front/app/partials/photo_view.html:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
10 | {{ load_error_text }}
11 |
12 |
13 |
14 | Loading ...
15 |
16 |
17 |
20 |
21 |
22 |
25 |
28 |
29 |
30 |
31 |
32 |
33 | {{ description }}
34 | This is something a wee bit longer that I hope will wrap and show me the correc tpath to enlightenment. Only through fire shall our sins be cleansed.
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/Lesson07/02_testing/front/app/services/albumservice.js:
--------------------------------------------------------------------------------
1 | (function () {
2 |
3 | function albumProvider ($http, $fileUploader) {
4 |
5 | var album_cache = {};
6 |
7 | this.getUploader = function (album_name, scope) {
8 | return $fileUploader.create({
9 | scope: scope,
10 | method: "PUT",
11 | url: "/v1/albums/" + album_name + "/photos.json"
12 | });
13 | };
14 |
15 | this.albumChanged = function (name) {
16 | if (album_cache[name]) delete album_cache[name];
17 | };
18 |
19 | this.getAlbums = function (callback) {
20 | $http.get("/v1/albums.json")
21 | .success(function (data, status, headers, conf) {
22 | callback(null, data);
23 | })
24 | .error(function (data, status, headers, conf) {
25 | callback(data);
26 | });
27 | };
28 |
29 | this.getAlbum = function (name, callback) {
30 | if (album_cache[name]) return callback(null, album_cache[name]);
31 |
32 | $http.get("/v1/albums/" + name + ".json")
33 | .success(function (data, status, headers, conf) {
34 | album_cache[name] = data;
35 | callback(null, data);
36 | })
37 | .error(function (data, status, headers, conf) {
38 | callback(data);
39 | });
40 | };
41 |
42 | this.getPhotosForAlbum = function (name, callback) {
43 | if (album_cache[name]) return callback(null, album_cache[name].photos);
44 |
45 | $http.get("/v1/albums/" + name + "/photos.json")
46 | .success(function (data, status, headers, conf) {
47 | album_cache[name] = data;
48 | callback(null, data);
49 | })
50 | .error(function (data, status, headers, conf) {
51 | callback(data);
52 | });
53 | };
54 |
55 |
56 | this.addAlbum = function (album_data, callback) {
57 |
58 | if (!album_data.name) return callback({ code: "missing_name" });
59 | if (!album_data.title) return callback({ code: "missing_title" });
60 | if (!album_data.description) return callback({ code: "missing_description" });
61 | if (!album_data.date) return callback({ code: "missing_date" });
62 | if (!is_valid_date(album_data.date)) return callback({ code: "bad_date" });
63 |
64 | $http.put("/v1/albums.json", album_data)
65 | .success(function (data, status, headers, conf) {
66 | callback(null, data);
67 | })
68 | .error(function (data, status, headers, conf) {
69 | callback(data);
70 | });
71 | };
72 | }
73 |
74 | photoApp.service("albumProvider", albumProvider);
75 |
76 |
77 |
78 |
79 |
80 | function is_valid_date(the_date) {
81 | if (the_date.match(/^[0-9]{2,4}[\-\/\. ,][0-9]{1,2}[\-\/\. ,][0-9]{1,2}$/)) {
82 | var d = new Date(the_date);
83 | return !isNaN(d.getTime());
84 | } else {
85 | return false;
86 | }
87 | }
88 |
89 |
90 |
91 | })();
92 |
--------------------------------------------------------------------------------
/Lesson07/02_testing/front/css/app.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | padding: 0;
4 | }
5 |
6 | div#top_bar {
7 | text-align: left;
8 | background-color: #f2f2f2;
9 | border-bottom: 1px solid #ddd;
10 | height: 60px;
11 | }
12 |
13 |
14 | div#top_bar a {
15 | text-decoration: none;
16 | }
17 | div#top_bar .glyphicon {
18 | float: left;
19 | font-size: 400%;
20 | padding-left: 20px;
21 | padding-bottom: 10px;
22 | padding-top: 3px;
23 | padding-right: 20px;
24 | color: #666;
25 | }
26 |
27 | div#top_bar div#title {
28 | border-left: 1px solid #ccc;
29 | font-family: Helvetica;
30 | font-size: 28px;
31 | height: 60px;
32 | padding-left: 10px;
33 | margin-left: 95px;
34 | padding-top: 12px;
35 | font-weight: 100;
36 | color: #666;
37 | }
38 |
39 |
40 | input[type=text] {
41 | padding: 3px;
42 | border-radius: 4px;
43 | border: 1px solid #bbb;
44 | }
45 |
46 | textarea {
47 | padding: 3px;
48 | border-radius: 4px;
49 | border: 1px solid #bbb;
50 | }
51 |
52 |
53 | div.album {
54 | float: left;
55 | width: 300px;
56 | margin-right: 10px;
57 | min-height: 200px;
58 | }
59 |
60 | div.album div.description {
61 | padding: 5px;
62 | }
63 |
64 | div.album div.panel-heading a {
65 | color: white;
66 | }
--------------------------------------------------------------------------------
/Lesson07/02_testing/front/fonts/glyphicons-halflings-regular.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcwan/AngularJSLiveLessons/cef58c015affd54f775a5415d81fa4799aa76f1e/Lesson07/02_testing/front/fonts/glyphicons-halflings-regular.eot
--------------------------------------------------------------------------------
/Lesson07/02_testing/front/fonts/glyphicons-halflings-regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcwan/AngularJSLiveLessons/cef58c015affd54f775a5415d81fa4799aa76f1e/Lesson07/02_testing/front/fonts/glyphicons-halflings-regular.ttf
--------------------------------------------------------------------------------
/Lesson07/02_testing/front/fonts/glyphicons-halflings-regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcwan/AngularJSLiveLessons/cef58c015affd54f775a5415d81fa4799aa76f1e/Lesson07/02_testing/front/fonts/glyphicons-halflings-regular.woff
--------------------------------------------------------------------------------
/Lesson07/02_testing/front/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
My Photo Albums
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/Lesson07/02_testing/front/js/angular-route.min.js:
--------------------------------------------------------------------------------
1 | /*
2 | AngularJS v1.2.16
3 | (c) 2010-2014 Google, Inc. http://angularjs.org
4 | License: MIT
5 | */
6 | (function(n,e,A){'use strict';function x(s,g,k){return{restrict:"ECA",terminal:!0,priority:400,transclude:"element",link:function(a,c,b,f,w){function y(){p&&(p.remove(),p=null);h&&(h.$destroy(),h=null);l&&(k.leave(l,function(){p=null}),p=l,l=null)}function v(){var b=s.current&&s.current.locals;if(e.isDefined(b&&b.$template)){var b=a.$new(),d=s.current;l=w(b,function(d){k.enter(d,null,l||c,function(){!e.isDefined(t)||t&&!a.$eval(t)||g()});y()});h=d.scope=b;h.$emit("$viewContentLoaded");h.$eval(u)}else y()}
7 | var h,l,p,t=b.autoscroll,u=b.onload||"";a.$on("$routeChangeSuccess",v);v()}}}function z(e,g,k){return{restrict:"ECA",priority:-400,link:function(a,c){var b=k.current,f=b.locals;c.html(f.$template);var w=e(c.contents());b.controller&&(f.$scope=a,f=g(b.controller,f),b.controllerAs&&(a[b.controllerAs]=f),c.data("$ngControllerController",f),c.children().data("$ngControllerController",f));w(a)}}}n=e.module("ngRoute",["ng"]).provider("$route",function(){function s(a,c){return e.extend(new (e.extend(function(){},
8 | {prototype:a})),c)}function g(a,e){var b=e.caseInsensitiveMatch,f={originalPath:a,regexp:a},k=f.keys=[];a=a.replace(/([().])/g,"\\$1").replace(/(\/)?:(\w+)([\?\*])?/g,function(a,e,b,c){a="?"===c?c:null;c="*"===c?c:null;k.push({name:b,optional:!!a});e=e||"";return""+(a?"":e)+"(?:"+(a?e:"")+(c&&"(.+?)"||"([^/]+)")+(a||"")+")"+(a||"")}).replace(/([\/$\*])/g,"\\$1");f.regexp=RegExp("^"+a+"$",b?"i":"");return f}var k={};this.when=function(a,c){k[a]=e.extend({reloadOnSearch:!0},c,a&&g(a,c));if(a){var b=
9 | "/"==a[a.length-1]?a.substr(0,a.length-1):a+"/";k[b]=e.extend({redirectTo:a},g(b,c))}return this};this.otherwise=function(a){this.when(null,a);return this};this.$get=["$rootScope","$location","$routeParams","$q","$injector","$http","$templateCache","$sce",function(a,c,b,f,g,n,v,h){function l(){var d=p(),m=r.current;if(d&&m&&d.$$route===m.$$route&&e.equals(d.pathParams,m.pathParams)&&!d.reloadOnSearch&&!u)m.params=d.params,e.copy(m.params,b),a.$broadcast("$routeUpdate",m);else if(d||m)u=!1,a.$broadcast("$routeChangeStart",
10 | d,m),(r.current=d)&&d.redirectTo&&(e.isString(d.redirectTo)?c.path(t(d.redirectTo,d.params)).search(d.params).replace():c.url(d.redirectTo(d.pathParams,c.path(),c.search())).replace()),f.when(d).then(function(){if(d){var a=e.extend({},d.resolve),c,b;e.forEach(a,function(d,c){a[c]=e.isString(d)?g.get(d):g.invoke(d)});e.isDefined(c=d.template)?e.isFunction(c)&&(c=c(d.params)):e.isDefined(b=d.templateUrl)&&(e.isFunction(b)&&(b=b(d.params)),b=h.getTrustedResourceUrl(b),e.isDefined(b)&&(d.loadedTemplateUrl=
11 | b,c=n.get(b,{cache:v}).then(function(a){return a.data})));e.isDefined(c)&&(a.$template=c);return f.all(a)}}).then(function(c){d==r.current&&(d&&(d.locals=c,e.copy(d.params,b)),a.$broadcast("$routeChangeSuccess",d,m))},function(c){d==r.current&&a.$broadcast("$routeChangeError",d,m,c)})}function p(){var a,b;e.forEach(k,function(f,k){var q;if(q=!b){var g=c.path();q=f.keys;var l={};if(f.regexp)if(g=f.regexp.exec(g)){for(var h=1,p=g.length;h