├── Module4
├── modules
│ ├── data.module.js
│ └── menuapp.module.js
├── templates
│ ├── home.template.html
│ ├── items.template.html
│ ├── categories.template.html
│ ├── categories.component.html
│ └── items.component.html
├── components
│ ├── items.component.js
│ └── categories.component.js
├── controllers
│ ├── categories.controller.js
│ └── items.controller.js
├── services
│ └── menudata.service.js
├── readme.md
├── routes
│ └── routes.js
└── index.html
├── Module5
├── lib
│ ├── ng-file-upload
│ │ ├── .versions
│ │ ├── FileAPI.flash.swf
│ │ ├── README.md
│ │ ├── package.js
│ │ ├── bower.json
│ │ ├── LICENSE
│ │ ├── ng-file-upload-shim.min.js
│ │ ├── ng-file-upload-shim.js
│ │ └── ng-file-upload.min.js
│ ├── jasmine-2.4.1
│ │ ├── jasmine_favicon.png
│ │ ├── boot.js
│ │ ├── console.js
│ │ ├── jasmine-html.js
│ │ └── jasmine.css
│ └── angular-ui-router.min.js
├── images
│ ├── menu-tile.jpg
│ ├── menu
│ │ ├── A
│ │ │ └── A.jpg
│ │ ├── B
│ │ │ └── B.jpg
│ │ ├── C
│ │ │ └── C.jpg
│ │ ├── D
│ │ │ └── D.jpg
│ │ ├── F
│ │ │ └── F.jpg
│ │ ├── L
│ │ │ └── L.jpg
│ │ ├── T
│ │ │ └── T.jpg
│ │ ├── V
│ │ │ └── V.jpg
│ │ ├── CM
│ │ │ └── CM.jpg
│ │ ├── CSR
│ │ │ └── CSR.jpg
│ │ ├── CU
│ │ │ └── CU.jpg
│ │ ├── DK
│ │ │ └── DK.jpg
│ │ ├── DS
│ │ │ └── DS.jpg
│ │ ├── FR
│ │ │ └── FR.jpg
│ │ ├── FY
│ │ │ └── FY.jpg
│ │ ├── NF
│ │ │ └── NF.jpg
│ │ ├── NL
│ │ │ └── NL.jpg
│ │ ├── NS
│ │ │ └── NS.jpg
│ │ ├── PF
│ │ │ └── PF.jpg
│ │ ├── SO
│ │ │ └── SO.jpg
│ │ ├── SP
│ │ │ └── SP.jpg
│ │ ├── SR
│ │ │ └── SR.jpg
│ │ ├── SS
│ │ │ └── SS.jpg
│ │ └── VG
│ │ │ └── VG.jpg
│ ├── star-k-logo.png
│ ├── jumbotron_1200.jpg
│ ├── jumbotron_768.jpg
│ ├── jumbotron_992.jpg
│ ├── specials-tile.jpg
│ ├── restaurant-logo.png
│ ├── restaurant-logo_large.png
│ ├── restaurant-logo_medium.png
│ ├── restaurant-logo_small.png
│ └── spinner.svg
├── fonts
│ ├── glyphicons-halflings-regular.eot
│ ├── glyphicons-halflings-regular.ttf
│ ├── glyphicons-halflings-regular.woff
│ └── glyphicons-halflings-regular.woff2
├── src
│ ├── public
│ │ ├── public.html
│ │ ├── public.module.js
│ │ ├── menu-category
│ │ │ ├── menu-category.component.js
│ │ │ └── menu-category.html
│ │ ├── menu
│ │ │ ├── menu.controller.js
│ │ │ └── menu.html
│ │ ├── menu-items
│ │ │ ├── menu-items.controller.js
│ │ │ └── menu-items.html
│ │ ├── menu-item
│ │ │ ├── menu-item.component.js
│ │ │ └── menu-item.html
│ │ ├── info
│ │ │ ├── info.controller.js
│ │ │ └── info.html
│ │ ├── signup
│ │ │ ├── signup.controller.js
│ │ │ └── signup.html
│ │ ├── home
│ │ │ └── home.html
│ │ └── public.routes.js
│ ├── common
│ │ ├── common.module.js
│ │ ├── loading
│ │ │ ├── loading.component.js
│ │ │ └── loading.interceptor.js
│ │ └── menu.service.js
│ └── restaurant.module.js
├── css
│ ├── common.css
│ ├── public.css
│ └── restaurant.css
├── readme.md
└── index.html
├── Module3
├── styles
│ └── styles.css
├── foundItems.html
├── index.html
├── readme.md
└── js
│ └── app.js
├── readme.md
├── Module1
├── app.js
├── readme.md
└── index.html
└── Module2
├── readme.md
├── app.js
└── index.html
/Module4/modules/data.module.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | 'use strict';
3 |
4 | angular.module('data', []);
5 | })();
6 |
--------------------------------------------------------------------------------
/Module4/templates/home.template.html:
--------------------------------------------------------------------------------
1 |
2 |
Welcome to Restaurant Menu App
3 |
4 |
--------------------------------------------------------------------------------
/Module4/templates/items.template.html:
--------------------------------------------------------------------------------
1 | Menu Category: {{itemsCtrl.categoryName}}
2 |
3 |
--------------------------------------------------------------------------------
/Module5/lib/ng-file-upload/.versions:
--------------------------------------------------------------------------------
1 | angular:angular@1.2.24
2 | danialf:ng-file-upload@12.0.3
3 | meteor@1.1.10
4 | underscore@1.0.4
5 |
--------------------------------------------------------------------------------
/Module5/images/menu-tile.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/igogra/Single-Page-Web-Applications-with-AngularJS/HEAD/Module5/images/menu-tile.jpg
--------------------------------------------------------------------------------
/Module5/images/menu/A/A.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/igogra/Single-Page-Web-Applications-with-AngularJS/HEAD/Module5/images/menu/A/A.jpg
--------------------------------------------------------------------------------
/Module5/images/menu/B/B.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/igogra/Single-Page-Web-Applications-with-AngularJS/HEAD/Module5/images/menu/B/B.jpg
--------------------------------------------------------------------------------
/Module5/images/menu/C/C.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/igogra/Single-Page-Web-Applications-with-AngularJS/HEAD/Module5/images/menu/C/C.jpg
--------------------------------------------------------------------------------
/Module5/images/menu/D/D.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/igogra/Single-Page-Web-Applications-with-AngularJS/HEAD/Module5/images/menu/D/D.jpg
--------------------------------------------------------------------------------
/Module5/images/menu/F/F.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/igogra/Single-Page-Web-Applications-with-AngularJS/HEAD/Module5/images/menu/F/F.jpg
--------------------------------------------------------------------------------
/Module5/images/menu/L/L.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/igogra/Single-Page-Web-Applications-with-AngularJS/HEAD/Module5/images/menu/L/L.jpg
--------------------------------------------------------------------------------
/Module5/images/menu/T/T.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/igogra/Single-Page-Web-Applications-with-AngularJS/HEAD/Module5/images/menu/T/T.jpg
--------------------------------------------------------------------------------
/Module5/images/menu/V/V.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/igogra/Single-Page-Web-Applications-with-AngularJS/HEAD/Module5/images/menu/V/V.jpg
--------------------------------------------------------------------------------
/Module5/images/menu/CM/CM.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/igogra/Single-Page-Web-Applications-with-AngularJS/HEAD/Module5/images/menu/CM/CM.jpg
--------------------------------------------------------------------------------
/Module5/images/menu/CSR/CSR.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/igogra/Single-Page-Web-Applications-with-AngularJS/HEAD/Module5/images/menu/CSR/CSR.jpg
--------------------------------------------------------------------------------
/Module5/images/menu/CU/CU.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/igogra/Single-Page-Web-Applications-with-AngularJS/HEAD/Module5/images/menu/CU/CU.jpg
--------------------------------------------------------------------------------
/Module5/images/menu/DK/DK.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/igogra/Single-Page-Web-Applications-with-AngularJS/HEAD/Module5/images/menu/DK/DK.jpg
--------------------------------------------------------------------------------
/Module5/images/menu/DS/DS.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/igogra/Single-Page-Web-Applications-with-AngularJS/HEAD/Module5/images/menu/DS/DS.jpg
--------------------------------------------------------------------------------
/Module5/images/menu/FR/FR.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/igogra/Single-Page-Web-Applications-with-AngularJS/HEAD/Module5/images/menu/FR/FR.jpg
--------------------------------------------------------------------------------
/Module5/images/menu/FY/FY.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/igogra/Single-Page-Web-Applications-with-AngularJS/HEAD/Module5/images/menu/FY/FY.jpg
--------------------------------------------------------------------------------
/Module5/images/menu/NF/NF.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/igogra/Single-Page-Web-Applications-with-AngularJS/HEAD/Module5/images/menu/NF/NF.jpg
--------------------------------------------------------------------------------
/Module5/images/menu/NL/NL.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/igogra/Single-Page-Web-Applications-with-AngularJS/HEAD/Module5/images/menu/NL/NL.jpg
--------------------------------------------------------------------------------
/Module5/images/menu/NS/NS.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/igogra/Single-Page-Web-Applications-with-AngularJS/HEAD/Module5/images/menu/NS/NS.jpg
--------------------------------------------------------------------------------
/Module5/images/menu/PF/PF.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/igogra/Single-Page-Web-Applications-with-AngularJS/HEAD/Module5/images/menu/PF/PF.jpg
--------------------------------------------------------------------------------
/Module5/images/menu/SO/SO.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/igogra/Single-Page-Web-Applications-with-AngularJS/HEAD/Module5/images/menu/SO/SO.jpg
--------------------------------------------------------------------------------
/Module5/images/menu/SP/SP.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/igogra/Single-Page-Web-Applications-with-AngularJS/HEAD/Module5/images/menu/SP/SP.jpg
--------------------------------------------------------------------------------
/Module5/images/menu/SR/SR.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/igogra/Single-Page-Web-Applications-with-AngularJS/HEAD/Module5/images/menu/SR/SR.jpg
--------------------------------------------------------------------------------
/Module5/images/menu/SS/SS.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/igogra/Single-Page-Web-Applications-with-AngularJS/HEAD/Module5/images/menu/SS/SS.jpg
--------------------------------------------------------------------------------
/Module5/images/menu/VG/VG.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/igogra/Single-Page-Web-Applications-with-AngularJS/HEAD/Module5/images/menu/VG/VG.jpg
--------------------------------------------------------------------------------
/Module5/images/star-k-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/igogra/Single-Page-Web-Applications-with-AngularJS/HEAD/Module5/images/star-k-logo.png
--------------------------------------------------------------------------------
/Module5/images/jumbotron_1200.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/igogra/Single-Page-Web-Applications-with-AngularJS/HEAD/Module5/images/jumbotron_1200.jpg
--------------------------------------------------------------------------------
/Module5/images/jumbotron_768.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/igogra/Single-Page-Web-Applications-with-AngularJS/HEAD/Module5/images/jumbotron_768.jpg
--------------------------------------------------------------------------------
/Module5/images/jumbotron_992.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/igogra/Single-Page-Web-Applications-with-AngularJS/HEAD/Module5/images/jumbotron_992.jpg
--------------------------------------------------------------------------------
/Module5/images/specials-tile.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/igogra/Single-Page-Web-Applications-with-AngularJS/HEAD/Module5/images/specials-tile.jpg
--------------------------------------------------------------------------------
/Module5/images/restaurant-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/igogra/Single-Page-Web-Applications-with-AngularJS/HEAD/Module5/images/restaurant-logo.png
--------------------------------------------------------------------------------
/Module5/images/restaurant-logo_large.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/igogra/Single-Page-Web-Applications-with-AngularJS/HEAD/Module5/images/restaurant-logo_large.png
--------------------------------------------------------------------------------
/Module5/images/restaurant-logo_medium.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/igogra/Single-Page-Web-Applications-with-AngularJS/HEAD/Module5/images/restaurant-logo_medium.png
--------------------------------------------------------------------------------
/Module5/images/restaurant-logo_small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/igogra/Single-Page-Web-Applications-with-AngularJS/HEAD/Module5/images/restaurant-logo_small.png
--------------------------------------------------------------------------------
/Module5/fonts/glyphicons-halflings-regular.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/igogra/Single-Page-Web-Applications-with-AngularJS/HEAD/Module5/fonts/glyphicons-halflings-regular.eot
--------------------------------------------------------------------------------
/Module5/fonts/glyphicons-halflings-regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/igogra/Single-Page-Web-Applications-with-AngularJS/HEAD/Module5/fonts/glyphicons-halflings-regular.ttf
--------------------------------------------------------------------------------
/Module5/lib/jasmine-2.4.1/jasmine_favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/igogra/Single-Page-Web-Applications-with-AngularJS/HEAD/Module5/lib/jasmine-2.4.1/jasmine_favicon.png
--------------------------------------------------------------------------------
/Module5/lib/ng-file-upload/FileAPI.flash.swf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/igogra/Single-Page-Web-Applications-with-AngularJS/HEAD/Module5/lib/ng-file-upload/FileAPI.flash.swf
--------------------------------------------------------------------------------
/Module4/templates/categories.template.html:
--------------------------------------------------------------------------------
1 |
2 |
Menu Categories
3 |
4 |
5 |
--------------------------------------------------------------------------------
/Module5/fonts/glyphicons-halflings-regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/igogra/Single-Page-Web-Applications-with-AngularJS/HEAD/Module5/fonts/glyphicons-halflings-regular.woff
--------------------------------------------------------------------------------
/Module5/fonts/glyphicons-halflings-regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/igogra/Single-Page-Web-Applications-with-AngularJS/HEAD/Module5/fonts/glyphicons-halflings-regular.woff2
--------------------------------------------------------------------------------
/Module5/src/public/public.html:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/Module4/modules/menuapp.module.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | 'use strict';
3 |
4 | angular.module('MenuApp', ['data', 'ui.router']).constant('ApiBasePath', "https://davids-restaurant.herokuapp.com");
5 | })();
6 |
--------------------------------------------------------------------------------
/Module5/src/public/public.module.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | "use strict";
3 | /**
4 | * Public restaurant application. Includes the common module and ui-router.
5 | */
6 | angular.module('public', ['ui.router', 'common']);
7 |
8 | })();
9 |
--------------------------------------------------------------------------------
/Module4/templates/categories.component.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | {{category.name}}
4 |
5 |
6 |
--------------------------------------------------------------------------------
/Module5/lib/ng-file-upload/README.md:
--------------------------------------------------------------------------------
1 | # angular-file-upload-bower
2 |
3 | bower distribution of [angular-file-upload](https://github.com/danialfarid/angular-file-upload).
4 | All issues and pull request must be sumbitted to [angular-file-upload](https://github.com/danialfarid/angular-file-upload)
5 |
6 |
--------------------------------------------------------------------------------
/Module4/components/items.component.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | 'use strict';
3 |
4 | angular.module('MenuApp')
5 | .component('items', {
6 | templateUrl: 'templates/items.component.html',
7 | bindings: {
8 | items: '<'
9 | }
10 | });
11 | })();
12 |
--------------------------------------------------------------------------------
/Module5/src/public/menu-category/menu-category.component.js:
--------------------------------------------------------------------------------
1 | (function () {
2 | "use strict";
3 |
4 | angular.module('public')
5 | .component('menuCategory', {
6 | templateUrl: 'src/public/menu-category/menu-category.html',
7 | bindings: {
8 | category: '<'
9 | }
10 | });
11 |
12 |
13 |
14 | })();
15 |
--------------------------------------------------------------------------------
/Module3/styles/styles.css:
--------------------------------------------------------------------------------
1 | h1 {
2 | margin-bottom: 30px;
3 | }
4 |
5 | input[type="text"] {
6 | width: 200px;
7 | float: left;
8 | }
9 |
10 | .narrow-button {
11 | float: left;
12 | margin-left: 10px;
13 | }
14 |
15 | .search {
16 | display: inline-block;
17 | margin-bottom: 10px;
18 | }
19 |
--------------------------------------------------------------------------------
/Module4/components/categories.component.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | 'use strict';
3 |
4 | angular.module('MenuApp')
5 | .component('categories', {
6 | templateUrl: 'templates/categories.component.html',
7 | bindings: {
8 | categories: '<'
9 | }
10 | });
11 | })();
12 |
--------------------------------------------------------------------------------
/Module5/src/public/menu/menu.controller.js:
--------------------------------------------------------------------------------
1 | (function () {
2 | "use strict";
3 |
4 | angular.module('public')
5 | .controller('MenuController', MenuController);
6 |
7 | MenuController.$inject = ['menuCategories'];
8 | function MenuController(menuCategories) {
9 | var $ctrl = this;
10 | $ctrl.menuCategories = menuCategories;
11 | }
12 |
13 |
14 | })();
15 |
--------------------------------------------------------------------------------
/Module5/src/public/menu-items/menu-items.controller.js:
--------------------------------------------------------------------------------
1 | (function () {
2 | "use strict";
3 |
4 | angular.module('public')
5 | .controller('MenuItemsController', MenuItemsController);
6 |
7 | MenuItemsController.$inject = ['menuItems'];
8 | function MenuItemsController(menuItems) {
9 | var $ctrl = this;
10 | $ctrl.menuItems = menuItems;
11 | }
12 |
13 | })();
14 |
--------------------------------------------------------------------------------
/Module5/src/common/common.module.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | "use strict";
3 |
4 | angular.module('common', [])
5 | .constant('ApiPath', 'https://aleksandar-gjorgievski.herokuapp.com')
6 | .config(config);
7 |
8 | config.$inject = ['$httpProvider'];
9 | function config($httpProvider) {
10 | $httpProvider.interceptors.push('loadingHttpInterceptor');
11 | }
12 |
13 | })();
14 |
--------------------------------------------------------------------------------
/Module5/css/common.css:
--------------------------------------------------------------------------------
1 | .loading-indicator {
2 | display: block;
3 | width: 70px;
4 | position: fixed;
5 | left: 0;
6 | right: 0;
7 | margin: 0 auto;
8 | top: 40%;
9 | z-index: 100;
10 | background-color: #FFF;
11 | }
12 |
13 | .loading-indicator img {
14 | width: 70px;
15 | background-color: #FFF;
16 | }
17 |
18 | .ui-view-placeholder {
19 | margin-top: 60px;
20 | }
21 |
--------------------------------------------------------------------------------
/Module4/controllers/categories.controller.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | 'use strict';
3 |
4 | angular.module('MenuApp').controller('categoriesController', categoriesController);
5 |
6 | categoriesController.$inject = ['MenuDataService', 'categories'];
7 |
8 | function categoriesController(MenuDataService, categories) {
9 | var categoriesCtrl = this;
10 | categoriesCtrl.categories = categories;
11 | }
12 | })();
13 |
--------------------------------------------------------------------------------
/Module5/src/public/menu-category/menu-category.html:
--------------------------------------------------------------------------------
1 |
9 |
--------------------------------------------------------------------------------
/Module5/src/public/menu/menu.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Substituting white rice with brown rice or fried rice after 3:00pm will be $1.50 for a pint and $2.50 for a quart.
5 |
6 |
7 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/Module5/src/restaurant.module.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | "use strict";
3 |
4 | /**
5 | * Restaurant module that includes the public module as a dependency
6 | */
7 | angular.module('restaurant', ['public'])
8 | .config(config);
9 |
10 | config.$inject = ['$urlRouterProvider'];
11 | function config($urlRouterProvider) {
12 |
13 | // If user goes to a path that doesn't exist, redirect to public root
14 | $urlRouterProvider.otherwise('/');
15 | }
16 |
17 | })();
18 |
--------------------------------------------------------------------------------
/Module5/lib/ng-file-upload/package.js:
--------------------------------------------------------------------------------
1 | Package.describe({
2 | name: "danialf:ng-file-upload",
3 | "version": "12.0.4",
4 | summary: "Lightweight Angular directive to upload files with optional FileAPI shim for cross browser support",
5 | git: "https://github.com/danialfarid/ng-file-upload.git"
6 | });
7 |
8 | Package.onUse(function (api) {
9 | api.use('angular:angular@1.2.0', 'client');
10 | api.addFiles('ng-file-upload-all.js', 'client');
11 | });
12 |
13 |
--------------------------------------------------------------------------------
/Module5/src/public/menu-items/menu-items.html:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | {{ menuItemsCtrl.menuItems.category.special_instructions}}
7 |
8 |
9 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/Module4/controllers/items.controller.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | 'use strict';
3 |
4 | angular.module('MenuApp').controller('itemsController', itemsController);
5 |
6 | itemsController.$inject = ['$stateParams', 'MenuDataService', 'items'];
7 |
8 | function itemsController($stateParams, MenuDataService, items) {
9 | var itemsCtrl = this;
10 | itemsCtrl.items = items;
11 | itemsCtrl.categoryName = $stateParams.categoryName;
12 | }
13 | })();
14 |
--------------------------------------------------------------------------------
/Module5/lib/ng-file-upload/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ng-file-upload",
3 | "main": "ng-file-upload.js",
4 | "homepage": "https://github.com/danialfarid/ng-file-upload",
5 | "dependencies": {
6 | "angular": ">1.2.0"
7 | },
8 | "authors": [
9 | "danialf "
10 | ],
11 | "description": "Lightweight Angular JS directive to upload files. Support drag&drop, paste image, progress and abort",
12 | "ignore": [],
13 | "license": "MIT"
14 | }
15 |
--------------------------------------------------------------------------------
/Module5/src/public/menu-item/menu-item.component.js:
--------------------------------------------------------------------------------
1 | (function () {
2 | "use strict";
3 |
4 | angular.module('public')
5 | .component('menuItem', {
6 | templateUrl: 'src/public/menu-item/menu-item.html',
7 | bindings: {
8 | menuItem: '<'
9 | },
10 | controller: MenuItemController
11 | });
12 |
13 |
14 | MenuItemController.$inject = ['ApiPath'];
15 | function MenuItemController(ApiPath) {
16 | var $ctrl = this;
17 | $ctrl.basePath = ApiPath;
18 | }
19 |
20 | })();
21 |
--------------------------------------------------------------------------------
/Module4/templates/items.component.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Name
5 | Short name
6 | Description
7 | Price
8 |
9 |
10 |
11 |
12 | {{categorieItem.name}}
13 | {{categorieItem.short_name}}
14 | {{categorieItem.description}}
15 | {{categorieItem.price_large | currency}}
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | #Single Page Web Applications with AngularJS
2 |
3 | Solutions to module assignments for the "Single Page Web Applications with AngularJS" Coursera MOOC taught by Johns Hopkins University.
4 |
5 | ##Course Outline
6 |
7 | - Module 1 | Introduction to AngularJS
8 | - Module 2 | Filters, Digest Cycle, Controller Inheritance, and Custom Services
9 | - Module 3 | Promises, Ajax, and Custom Directives
10 | - Module 4 | Components, Events, Modules, and Routing
11 | - Module 5 | Form Validation, Testing, and Restaurant Site Development
12 |
--------------------------------------------------------------------------------
/Module5/src/public/info/info.controller.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | 'use strict';
3 |
4 | var infoController = function(MenuService, ApiPath) {
5 | var vm = this;
6 | vm.apiPath = ApiPath;
7 |
8 | vm.signedUp = false;
9 |
10 | vm.user = MenuService.getUser();
11 | console.log('User is', vm.user);
12 | if (angular.equals(vm.user, {})) {
13 | vm.signedUp = false;
14 | } else {
15 | vm.signedUp = true;
16 | }
17 | };
18 |
19 | infoController.$inject = ['MenuService', 'ApiPath'];
20 | angular.module('public').controller('InfoController', infoController);
21 | })();
--------------------------------------------------------------------------------
/Module3/foundItems.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
{{item.name}}
7 |
{{item.short_name}}
8 |
{{item.description}}
9 |
10 |
11 |
12 |
13 |
14 | {{menu.onEmpty}}
15 |
--------------------------------------------------------------------------------
/Module5/src/common/loading/loading.component.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | "use strict";
3 |
4 | angular.module('common')
5 | .component('loading', {
6 | template: ' ',
7 | controller: LoadingController
8 | });
9 |
10 |
11 | LoadingController.$inject = ['$rootScope'];
12 | function LoadingController ($rootScope) {
13 | var $ctrl = this;
14 | var listener;
15 |
16 | $ctrl.$onInit = function() {
17 | $ctrl.show = false;
18 | listener = $rootScope.$on('spinner:activate', onSpinnerActivate);
19 | };
20 |
21 | $ctrl.$onDestroy = function() {
22 | listener();
23 | };
24 |
25 | function onSpinnerActivate(event, data) {
26 | $ctrl.show = data.on;
27 | }
28 | }
29 |
30 | })();
31 |
--------------------------------------------------------------------------------
/Module5/src/public/menu-item/menu-item.html:
--------------------------------------------------------------------------------
1 |
17 |
--------------------------------------------------------------------------------
/Module5/src/public/info/info.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
Showing information for user.
5 |
First name: {{infoCtrl.user.firstName}}
6 |
Last name: {{infoCtrl.user.lastName}}
7 |
Email: {{infoCtrl.user.email}}
8 |
Phone: {{infoCtrl.user.phone}}
9 |
Favorite dish: {{infoCtrl.user.favoriteDishDetails.name}}
10 |
{{infoCtrl.user.favoriteDishDetails.description}}
11 |
12 |
13 |
14 |
15 |
18 |
19 |
--------------------------------------------------------------------------------
/Module4/services/menudata.service.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | 'use strict';
3 |
4 | angular.module('data').service('MenuDataService', MenuDataService);
5 |
6 | MenuDataService.$inject = ['$http', 'ApiBasePath'];
7 |
8 | function MenuDataService($http, ApiBasePath) {
9 | var service = this;
10 |
11 | service.getAllCategories = function() {
12 | return $http({
13 | method: "GET",
14 | url: (ApiBasePath + '/categories.json')
15 | }).then(function(response) {;
16 | return response.data;
17 | });
18 | };
19 |
20 | service.getItemsForCategory = function(categoryShortName) {
21 | return $http({
22 | method: "GET",
23 | url: (ApiBasePath + '/menu_items.json?category=' + categoryShortName)
24 | }).then(function(response) {
25 | return response.data.menu_items;
26 | });
27 | };
28 | }
29 | })();
30 |
--------------------------------------------------------------------------------
/Module1/app.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | 'use strict';
3 |
4 | angular.module('LunchCheck', [])
5 | .controller('LunchCheckController', LunchCheckController);
6 |
7 | LunchCheckController.$inject = ['$scope'];
8 |
9 | function LunchCheckController($scope) {
10 | $scope.dishes = '';
11 | $scope.message = '';
12 | $scope.checked = false;
13 |
14 | $scope.checkLunch = function() {
15 | if ($scope.dishes.trim().length === 0) {
16 | $scope.empty = true;
17 | } else {
18 | $scope.checked = true;
19 | $scope.empty = false;
20 | var arrayDishes = $scope.dishes.split(',');
21 | var arrayDishesWithoutEmptys = arrayDishes.filter(function(v) {
22 | return v.trim() !== '';
23 | });
24 |
25 | if (arrayDishesWithoutEmptys.length <= 3) {
26 | $scope.message = 'Enjoy!';
27 | } else {
28 | $scope.message = 'Too much!';
29 | }
30 | }
31 | };
32 | }
33 | })();
34 |
--------------------------------------------------------------------------------
/Module5/lib/ng-file-upload/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2013 danialfarid
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of
6 | this software and associated documentation files (the "Software"), to deal in
7 | the Software without restriction, including without limitation the rights to
8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 | the Software, and to permit persons to whom the Software is furnished to do so,
10 | subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/Module5/src/common/menu.service.js:
--------------------------------------------------------------------------------
1 | (function () {
2 | "use strict";
3 |
4 | angular.module('common')
5 | .service('MenuService', MenuService);
6 |
7 |
8 | MenuService.$inject = ['$http', 'ApiPath'];
9 | function MenuService($http, ApiPath) {
10 | var service = this;
11 | service.user = {};
12 |
13 | service.saveUser = function(user) {
14 | service.user = angular.copy(user);
15 | console.log(service.user);
16 | }
17 |
18 | service.getUser = function() {
19 | return service.user;
20 | }
21 |
22 | service.getCategories = function () {
23 | return $http.get(ApiPath + '/categories.json').then(function (response) {
24 | return response.data;
25 | });
26 | };
27 |
28 |
29 | service.getMenuItems = function (category) {
30 | var config = {};
31 | if (category) {
32 | config.params = {'category': category};
33 | }
34 |
35 | return $http.get(ApiPath + '/menu_items.json', config).then(function (response) {
36 | return response.data;
37 | });
38 | };
39 |
40 | service.getFavoriteDish = function(short_name) {
41 | return $http.get(ApiPath + '/menu_items/' + short_name + '.json');
42 | }
43 |
44 | }
45 |
46 |
47 |
48 | })();
49 |
--------------------------------------------------------------------------------
/Module5/src/public/signup/signup.controller.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | 'use strict';
3 |
4 | var signupController = function(MenuService) {
5 | var vm = this;
6 |
7 | vm.user = {};
8 | vm.favoriteDish = {};
9 |
10 | vm.showError = false; // When this value is true error about the favorite dish wiil be shown
11 | vm.showMessage = false; // When this value is true message about successfull signup will be shown
12 |
13 | vm.signup = function(form) {
14 | vm.showError = false;
15 | vm.showMessage = false;
16 | // If the form is not valid don't submit
17 | if(form.$invalid) {
18 | console.log('The form is not valid');
19 | return;
20 | }
21 |
22 | MenuService.getFavoriteDish(vm.user.favoriteDish).then(function(response) {
23 | vm.user.favoriteDishDetails = response.data;
24 | console.log(vm.favoriteDish);
25 | MenuService.saveUser(vm.user);
26 | vm.showMessage = true;
27 | }, function(error) {
28 | console.log(error);
29 | vm.showError = true;
30 | });
31 |
32 | }
33 | };
34 |
35 |
36 | signupController.$inject = ['MenuService'];
37 | angular.module('public').controller('SignupController', signupController);
38 | })();
--------------------------------------------------------------------------------
/Module5/src/public/home/home.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
23 |
24 |
--------------------------------------------------------------------------------
/Module5/src/common/loading/loading.interceptor.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | "use strict";
3 |
4 | angular.module('common')
5 | .factory('loadingHttpInterceptor', LoadingHttpInterceptor);
6 |
7 | LoadingHttpInterceptor.$inject = ['$rootScope', '$q'];
8 | /**
9 | * Tracks when a request begins and finishes. When a
10 | * request starts, a progress event is emitted to allow
11 | * listeners to determine when a request has been initiated.
12 | * When the response completes or a response error occurs,
13 | * we assume the request has ended and emit a finish event.
14 | */
15 | function LoadingHttpInterceptor($rootScope, $q) {
16 |
17 | var loadingCount = 0;
18 | var loadingEventName = 'spinner:activate';
19 |
20 | return {
21 | request: function (config) {
22 | // console.log("Inside interceptor, config: ", config);
23 |
24 | if (++loadingCount === 1) {
25 | $rootScope.$broadcast(loadingEventName, {on: true});
26 | }
27 |
28 | return config;
29 | },
30 |
31 | response: function (response) {
32 | if (--loadingCount === 0) {
33 | $rootScope.$broadcast(loadingEventName, {on: false});
34 | }
35 |
36 | return response;
37 | },
38 |
39 | responseError: function (response) {
40 | if (--loadingCount === 0) {
41 | $rootScope.$broadcast(loadingEventName, {on: false});
42 | }
43 |
44 | return $q.reject(response);
45 | }
46 | };
47 | }
48 |
49 | })();
50 |
--------------------------------------------------------------------------------
/Module4/readme.md:
--------------------------------------------------------------------------------
1 | # Assignment Instructions
2 |
3 | ## General Idea
4 | Super simple idea behind this week's assignment: use the restaurant menu REST API to create a master/detail view pair.
5 |
6 | Your application should have 3 views (i.e., 3 view states): home (`home`), categories list (`categories`), items list (`items`).
7 |
8 | As long as the views are functional and readable, the styling does not really matter and is not graded.
9 |
10 | When the user goes to `/` path in your application, a home screen should be shown. It's up to you what you place on the home screen. You can just say "Welcome to our Restaurant". The home screen should have a link to a list of categories of menu items in the restaurant. Clicking that link would obviously take the user to the `/categories` view.
11 |
12 | The categories view should list all available categories of items on the menu. Each listing should be a link. Clicking that link should take the user to the `/items` view. Note that since what the `items` view state shows is dependent on which category the user clicked, the URL mapping will need to have a parameter in it. I.e., don't take the URLs I am listing in the assignment description as literal URLs. They are just naming hints.
13 |
14 | Make sure that if, while viewing the list of menu items for a particular category, the user copies the URL in the browser's address bar and pastes it into a new tab or a different browser, that the view is the same as the original one.
15 |
16 | [See my solution web page](https://igogra.github.io/Single-Page-Web-Applications-with-AngularJS/Module4/)
17 |
--------------------------------------------------------------------------------
/Module1/readme.md:
--------------------------------------------------------------------------------
1 | # Assignment Instructions
2 |
3 | ## General Idea
4 | The idea of this assignment is to create a front-end application that presents the user with a textbox where they can list comma-separated items they usually eat for lunch. Once that's entered, the user has to click the "Check If Too Much" button.
5 |
6 | If the number of items in the textbox is less than or equal to 3 (e.g., 1, 2, or 3), a message should show up under to the textbox saying "Enjoy!". If the number of items is greater than 3 (4, 5, and above), the message "Too much!" should show up under the textbox.
7 |
8 | If the textbox is empty and the user clicks the "Check If Too Much" button, the message "Please enter data first" should show up. 'Empty' here means either `""` (empty string) or a string with just spaces in it. (Hint: AngularJS `ng-model` already performs the trimming for you, so there shouldn't be anything you need to do.)
9 |
10 | Only 1 message should be shown at any given time. In other words, if you have both messages "Enjoy!" and "Too much!" showing up at the same time, it's an error.
11 |
12 | You are not required to handle a case where there is no item between some commas. For example, you are free to consider this case `item 1, item2,,item3` or this case `item 1, item2, ,item3` as 4 items in the list. However, you can implement checking for an 'empty' item as a bonus feature (ungraded). Please make sure to put a comment somewhere next to the input textbox stating that you do NOT consider and empty item, i.e., `, ,` as an item towards to the count.
13 |
14 | [See my solution web page](https://igogra.github.io/Single-Page-Web-Applications-with-AngularJS/Module1/)
15 |
--------------------------------------------------------------------------------
/Module4/routes/routes.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | 'use strict';
3 |
4 | angular.module('MenuApp').config(RoutesConfig);
5 |
6 | RoutesConfig.$inject = ['$stateProvider', '$urlRouterProvider'];
7 |
8 | function RoutesConfig($stateProvider, $urlRouterProvider) {
9 | $urlRouterProvider.otherwise('/');
10 |
11 | $stateProvider
12 | .state('home', {
13 | url: '/',
14 | templateUrl: 'templates/home.template.html'
15 | })
16 | .state('categories', {
17 | url: '/categories',
18 | templateUrl: 'templates/categories.template.html',
19 | controller: 'categoriesController as categoriesCtrl',
20 | resolve: {
21 | categories: ['MenuDataService', function(MenuDataService) {
22 | return MenuDataService.getAllCategories();
23 | }]
24 | }
25 | })
26 | .state('items', {
27 | url: '/categories/{categoryShortName}',
28 | templateUrl: 'templates/items.template.html',
29 | controller: 'itemsController as itemsCtrl',
30 | params: {
31 | categoryShortName: null,
32 | categoryName: null
33 | },
34 | resolve: {
35 | items: ['$stateParams', 'MenuDataService', function($stateParams, MenuDataService) {
36 | return MenuDataService.getItemsForCategory($stateParams.categoryShortName);
37 | }]
38 | }
39 | });
40 | }
41 | })();
42 |
--------------------------------------------------------------------------------
/Module1/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Lunch Checker
9 |
10 |
11 |
12 |
16 |
17 |
18 |
19 |
20 |
Lunch Checker
21 |
22 |
23 |
24 |
25 | Check If Too Much
26 |
27 |
{{message}}
28 |
Please enter data first
29 |
30 |
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/Module5/src/public/public.routes.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | 'use strict';
3 |
4 | angular.module('public')
5 | .config(routeConfig);
6 |
7 | /**
8 | * Configures the routes and views
9 | */
10 | routeConfig.$inject = ['$stateProvider'];
11 | function routeConfig ($stateProvider) {
12 | // Routes
13 | $stateProvider
14 | .state('public', {
15 | absract: true,
16 | templateUrl: 'src/public/public.html'
17 | })
18 | .state('public.home', {
19 | url: '/',
20 | templateUrl: 'src/public/home/home.html'
21 | })
22 | .state('public.menu', {
23 | url: '/menu',
24 | templateUrl: 'src/public/menu/menu.html',
25 | controller: 'MenuController',
26 | controllerAs: 'menuCtrl',
27 | resolve: {
28 | menuCategories: ['MenuService', function (MenuService) {
29 | return MenuService.getCategories();
30 | }]
31 | }
32 | })
33 | .state('public.menuitems', {
34 | url: '/menu/{category}',
35 | templateUrl: 'src/public/menu-items/menu-items.html',
36 | controller: 'MenuItemsController',
37 | controllerAs: 'menuItemsCtrl',
38 | resolve: {
39 | menuItems: ['$stateParams','MenuService', function ($stateParams, MenuService) {
40 | return MenuService.getMenuItems($stateParams.category);
41 | }]
42 | }
43 | })
44 | .state('public.signup', {
45 | url: '/signup',
46 | templateUrl: 'src/public/signup/signup.html',
47 | controller: 'SignupController',
48 | controllerAs: 'signupCtrl'
49 | })
50 | .state('public.info', {
51 | url: '/info',
52 | templateUrl: 'src/public/info/info.html',
53 | controller: 'InfoController',
54 | controllerAs: 'infoCtrl'
55 | });
56 | }
57 | })();
58 |
--------------------------------------------------------------------------------
/Module2/readme.md:
--------------------------------------------------------------------------------
1 | # Assignment Instructions
2 |
3 | ## General Idea
4 | The idea of this assignment is to create a "check off" shopping List application.
5 |
6 | Think of being in a store with a shopping list that allows you to "check off" the items you've already bought, except instead of checking them off, the bought item simply moves to the "Already Bought" list.
7 |
8 | Your HTML page should display 2 lists, one titled "To Buy" and the other "Already Bought".
9 |
10 | The "To Buy" list should be pre-populated with a list of at least 5 items. (Hint: Use an array of object literals, where each item will be similar to { name: "cookies", quantity: 10 }) Each shopping list item is to have a name and quantity. It should be displayed to the user in the format of Buy item_quantity item_name. For example, shopping list item { name: "cookies", quantity: 10 } would be listed as Buy 10 cookies.
11 |
12 | Next to each item in the list should be a button with the label "Bought". When the user clicks on the "Bought" button, its associated item should be removed from the "To Buy" list and appear in the "Already Bought" list.
13 |
14 | The "Already Bought" list should initially be empty and display a message "Nothing bought yet". Make sure the message appears only when the list is empty. Once something is "bought" and appears on this list, the format of each item in the list should be Bought item_quantity item_name. For example, the bought item of 10 cookies mentioned before would appear in this list as Bought 10 cookies.
15 |
16 | Once the user "buys" every item on the "To Buy" list, i.e., clicks on the "Bought" button for every item in the "To Buy" list, instead of the empty "To Buy" list, display the message "Everything is bought!"
17 |
18 | [See my solution web page](https://igogra.github.io/Single-Page-Web-Applications-with-AngularJS/Module2/)
19 |
--------------------------------------------------------------------------------
/Module3/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Narrow Down Your Menu Choice
9 |
10 |
11 |
12 |
13 |
14 |
18 |
19 |
20 |
21 |
22 |
Narrow Down Your Chinese Menu Choice
23 |
24 |
25 |
26 | Narrow It Down For Me!
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/Module2/app.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | 'use strict';
3 |
4 | angular.module('ShoppingListCheckOff', [])
5 | .controller('ToBuyController', ToBuyController)
6 | .controller('AlreadyBoughtController', AlreadyBoughtController)
7 | .service('ShoppingListCheckOffService', ShoppingListCheckOffService);
8 |
9 | ToBuyController.$inject = ['ShoppingListCheckOffService'];
10 |
11 | function ToBuyController(ShoppingListCheckOffService) {
12 | var toBuyList = this;
13 |
14 | toBuyList.items = ShoppingListCheckOffService.getToBuyItems();
15 |
16 | toBuyList.buyItem = function(itemIndex) {
17 | ShoppingListCheckOffService.buyItem(itemIndex);
18 | };
19 | }
20 |
21 | AlreadyBoughtController.$inject = ['ShoppingListCheckOffService'];
22 |
23 | function AlreadyBoughtController(ShoppingListCheckOffService) {
24 | var alreadyBougthList = this;
25 |
26 | alreadyBougthList.items = ShoppingListCheckOffService.getAlreadyBoughtItems();
27 | }
28 |
29 | function ShoppingListCheckOffService() {
30 | var service = this;
31 | var toBuyItems = [
32 | { name: "cookies", quantity: 10 },
33 | { name: "cokes", quantity: 2 },
34 | { name: "beers", quantity: 6 },
35 | { name: "apples", quantity: 4 },
36 | { name: "bananas", quantity: 7 }
37 | ];
38 | var alreadyBoughtItems = [];
39 |
40 | service.buyItem = function(itemIndex) {
41 | var item = toBuyItems[itemIndex];
42 |
43 | alreadyBoughtItems.push(item);
44 | toBuyItems.splice(itemIndex, 1);
45 | };
46 |
47 | service.getToBuyItems = function() {
48 | return toBuyItems;
49 | };
50 |
51 | service.getAlreadyBoughtItems = function() {
52 | return alreadyBoughtItems;
53 | };
54 | }
55 | })();
56 |
--------------------------------------------------------------------------------
/Module5/readme.md:
--------------------------------------------------------------------------------
1 | # Assignment Instructions
2 |
3 | ## General Idea
4 | Your starting point for this assignment will be the code in the `examples/Lecture59` folder.
5 |
6 | Your task is fairly simply.
7 |
8 | First, change the 2 buttons at the top of the website to say `My Info` and `Sign Up` instead of `About` and `Awards`.
9 |
10 | **Task 1:**
11 | When the user clicks on the `Sign Up` button, they should be taken to a view that lets them "sign up" for the newsletter (that will never come :-) ) of the restaurant. The sign up form should ask for the following information: first name, last name, email address, and phone number. It should also ask the user to specify the menu number that's their favorite dish. (The menu number is the `short_name` attribute of each menu item).
12 |
13 | Everything in the form (except th `short_name`) must be validated through AngularJS validation we learned in this module. When the user clicks the `Submit` button (after all other fields are validated), try to retrieve the menu item the user specified as their favorite through the following REST endpoint https://YOUR-CHOSEN-SUBDOMAIN.herokuapp.com/menu_items/SHORT-NAME.json, where `YOUR-CHOSEN-SUBDOMAIN` is the subdomain discussed in Lecture50 (Restaurant Server Setup), and the `SHORT-NAME` is the name the user provided. If the server returns an error, you will know that the item name specified is not valid. If that's the case, display a message next to the favorite choice saying `No such menu number exists`. (See bonus for more)
14 |
15 | If everything is valid, save the user's preference somewhere in your client app such that you can retrieve it in another view/component/controller/etc. (Hint: think service). Once saved, display a message below the form saying `Your information has been saved`.
16 |
17 | **Task 2:**
18 | When the user clicks on `My Info` button, they should be taken to another view where it shows them their "registered" information, including the favorite menu item they picked. When showing the favorite menu item, display the picture of the menu item as well as its title and description.
19 |
20 | If the user hasn't yet "registered" through the `Sign Up` button, simply display a message saying: `Not Signed Up Yet. Sign up Now!`. The words "Sign up Now!" should be a link to the same view as the `Sign Up` link points to.
21 |
22 | [See my solution web page](https://igogra.github.io/Single-Page-Web-Applications-with-AngularJS/Module5/)
23 |
--------------------------------------------------------------------------------
/Module3/readme.md:
--------------------------------------------------------------------------------
1 | # Assignment Instructions
2 |
3 | ## General Idea
4 | You are going to be building a much simplified search of the menu item descriptions using the restaurant server REST API we used in Lecture 25, Part 2.
5 |
6 | The idea here is for the user to search the descriptions of menu items. Then, given the list of matches of his search, give the user the ability to throw the items they for sure don't want off the list, thus narrowing it down to what they do want.
7 |
8 | Your task is create a text box and a button with the label "Narrow It Down For Me!".
9 |
10 | Initially, the user should just see a screen with the textbox and the "Narrow It Down For Me!" button. Once the user enters something into the textbox and clicks the button, your app will reach out to the server and retrieve the list of menu items for the entire menu. Once retrieved, your task is to loop through all the items and, for each item, do a simple check if the string being searched for by the user appears anywhere in the description of the item. If it does, that item gets placed in a special found array. If it doesn't, you simply move on to the next item.
11 |
12 | Once your app goes through all the items, it should display the found list of items. Each item in the list should show the name of the menu item, its short_name, and the description. You can display the items in a simple unordered list, with each piece of information separated by a comma. OR be fancier and use some sort of a grid. Either way is fine. We are not concentrating on style in this class.
13 |
14 | You should also provide a "Don't want this one!" button next to each item in the list to give the user the ability to remove an item from that list.
15 |
16 | If nothing is found as a result of the search OR if the user leaves the textbox empty and clicks the "Narrow It Down For Me!" button, you should simply display the message "Nothing found".
17 |
18 | To make things a bit easier, you can retrieve the items from the server every time the user clicks the "Narrow It Down For Me!" button. You don't have to cache the response. In other words, no matter what actions the user has taken, if the "Narrow It Down For Me!" button is clicked, all the data gets wiped out and the whole process starts all over again. No requirement to remember what the user chose to throw off the list last time.
19 |
20 | [See my solution web page](https://igogra.github.io/Single-Page-Web-Applications-with-AngularJS/Module3/)
21 |
--------------------------------------------------------------------------------
/Module3/js/app.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | 'use strict';
3 |
4 | angular.module('NarrowItDownApp', [])
5 | .controller('NarrowItDownController', NarrowItDownController)
6 | .service('MenuSearchService', MenuSearchService)
7 | .constant('ApiBasePath', "https://davids-restaurant.herokuapp.com")
8 | .directive('foundItems', FoundItems);
9 |
10 | function FoundItems() {
11 | var ddo = {
12 | restrict: 'E',
13 | templateUrl: 'foundItems.html',
14 | scope: {
15 | foundItems: '<',
16 | onEmpty: '<',
17 | onRemove: '&'
18 | },
19 | controller: NarrowItDownController,
20 | controllerAs: 'menu',
21 | bindToController: true
22 | };
23 |
24 | return ddo;
25 | }
26 |
27 | NarrowItDownController.$inject = ['MenuSearchService'];
28 |
29 | function NarrowItDownController(MenuSearchService) {
30 | var menu = this;
31 | menu.shortName = '';
32 |
33 | menu.matchedMenuItems = function(searchTerm) {
34 | var promise = MenuSearchService.getMatchedMenuItems(searchTerm);
35 |
36 | promise.then(function(items) {
37 | if (items && items.length > 0) {
38 | menu.message = '';
39 | menu.found = items;
40 | } else {
41 | menu.message = 'Nothing found!';
42 | menu.found = [];
43 | }
44 | });
45 | };
46 |
47 | menu.removeMenuItem = function(itemIndex) {
48 | menu.found.splice(itemIndex, 1);
49 | }
50 | }
51 |
52 | MenuSearchService.$inject = ['$http', 'ApiBasePath'];
53 |
54 | function MenuSearchService($http, ApiBasePath) {
55 | var service = this;
56 |
57 | service.getMatchedMenuItems = function(searchTerm) {
58 | return $http({
59 | method: "GET",
60 | url: (ApiBasePath + "/menu_items.json")
61 | }).then(function(response) {
62 | var foundItems = [];
63 |
64 | for (var i = 0; i < response.data['menu_items'].length; i++) {
65 | if (searchTerm.length > 0 && response.data['menu_items'][i]['description'].toLowerCase().indexOf(searchTerm) !== -1) {
66 | foundItems.push(response.data['menu_items'][i]);
67 | }
68 | }
69 |
70 | return foundItems;
71 | });
72 | };
73 | }
74 | })();
75 |
--------------------------------------------------------------------------------
/Module4/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Restaurant Menu App
9 |
10 |
11 |
12 |
15 |
16 |
17 |
21 |
22 |
23 |
24 |
25 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/Module2/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Shopping List Check Off
9 |
10 |
11 |
12 |
13 |
17 |
37 |
38 |
39 |
40 |
41 |
Shopping List Check Off
42 |
43 |
44 |
45 |
To Buy:
46 |
47 | Buy {{item.quantity}} {{item.name}}
48 | Buy
49 |
50 |
51 |
Everything is bought!
52 |
53 |
54 |
55 |
Already Bought:
56 |
57 | Bought {{item.quantity}} {{item.name}}
58 |
59 |
Nothing bought yet.
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
--------------------------------------------------------------------------------
/Module5/images/spinner.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Module5/src/public/signup/signup.html:
--------------------------------------------------------------------------------
1 | Signup for our newstler that will never come!
2 |
3 |
4 |
5 |
6 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/Module5/css/public.css:
--------------------------------------------------------------------------------
1 | /* HOME PAGE */
2 | .container .jumbotron {
3 | box-shadow: 0 0 50px #3F0C1F;
4 | border: 2px solid #3F0C1F;
5 | }
6 |
7 | #menu-tile, #specials-tile, #map-tile {
8 | height: 250px;
9 | width: 100%;
10 | margin-bottom: 15px;
11 | position: relative;
12 | border: 2px solid #3F0C1F;
13 | overflow: hidden;
14 | }
15 | #menu-tile:hover, #specials-tile:hover, #map-tile:hover {
16 | box-shadow: 0 1px 5px 1px #cccccc;
17 | }
18 | #menu-tile {
19 | background: url('../images/menu-tile.jpg') no-repeat;
20 | background-position: center;
21 | }
22 | #specials-tile {
23 | background: url('../images/specials-tile.jpg') no-repeat;
24 | background-position: center;
25 | }
26 | #menu-tile span, #specials-tile span, #map-tile span {
27 | position: absolute;
28 | bottom: 0;
29 | right: 0;
30 | width: 100%;
31 | text-align: center;
32 | font-size: 1.6em;
33 | text-transform: uppercase;
34 | background-color: #000;
35 | color: #fff;
36 | opacity: .8;
37 | }
38 | /* END HOME PAGE */
39 |
40 | /* MENU CATEGORIES PAGE */
41 | .category-tile {
42 | position: relative;
43 | border: 2px solid #3F0C1F;
44 | overflow: hidden;
45 | width: 200px;
46 | height: 200px;
47 | margin: 0 auto 15px;
48 | }
49 | .category-tile span {
50 | position: absolute;
51 | bottom: 0;
52 | right: 0;
53 | width: 100%;
54 | text-align: center;
55 | font-size: 1.2em;
56 | text-transform: uppercase;
57 | background-color: #000;
58 | color: #fff;
59 | opacity: .8;
60 | }
61 | .category-tile:hover {
62 | box-shadow: 0 1px 5px 1px #cccccc;
63 | }
64 |
65 | #menu-categories-title + div {
66 | margin-bottom: 50px;
67 | }
68 | /* END MENU CATEGORIES PAGE */
69 |
70 | /* SINGLE CATEGORY PAGE */
71 | .menu-item-tile {
72 | margin-bottom: 25px;
73 | }
74 | .menu-item-tile hr {
75 | width: 80%;
76 | }
77 | .menu-item-tile .menu-item-price {
78 | font-size: 1.1em;
79 | text-align: right;
80 | margin-top: -15px;
81 | margin-right: -15px;
82 | }
83 | .menu-item-tile .menu-item-price span {
84 | font-size: .6em;
85 | }
86 | .menu-item-photo {
87 | position: relative;
88 | border: 2px solid #3F0C1F;
89 | overflow: hidden;
90 | padding: 0;
91 | margin-right: -15px;
92 | margin-left: auto;
93 | margin-bottom: 20px;
94 | max-width: 250px;
95 | }
96 | .menu-item-photo div {
97 | position: absolute;
98 | bottom: 0;
99 | right: 0;
100 | width: 80px;
101 | background-color: #557c3e;
102 | text-align: center;
103 | }
104 | .menu-item-description {
105 | padding-right: 30px;
106 | }
107 | h3.menu-item-title {
108 | margin: 0 0 10px;
109 | }
110 | .menu-item-details {
111 | font-size: .9em;
112 | font-style: italic;
113 | }
114 | /* END SINGLE CATEGORY PAGE */
115 |
116 |
117 | /********** Large devices only **********/
118 | @media (min-width: 1200px) {
119 | .container .jumbotron {
120 | background: url('../images/jumbotron_1200.jpg') no-repeat;
121 | height: 675px;
122 | }
123 | }
124 |
125 | /********** Medium devices only **********/
126 | @media (min-width: 992px) and (max-width: 1199px) {
127 | /* Home Page */
128 | .container .jumbotron {
129 | background: url('../images/jumbotron_992.jpg') no-repeat;
130 | height: 558px;
131 | }
132 | /* End Home Page */
133 | }
134 |
135 | /********** Small devices only **********/
136 | @media (min-width: 768px) and (max-width: 991px) {
137 | /* Home Page */
138 | .container .jumbotron {
139 | background: url('../images/jumbotron_768.jpg') no-repeat;
140 | height: 432px;
141 | }
142 | /* End Home Page */
143 | }
144 |
145 | /********** Extra small devices only **********/
146 | @media (max-width: 767px) {
147 | /* Home Page */
148 | .container .jumbotron {
149 | margin-top: 30px;
150 | padding: 0;
151 | }
152 | #menu-tile, #specials-tile {
153 | width: 360px;
154 | margin: 0 auto 15px;
155 | }
156 |
157 | .menu-item-photo {
158 | margin-right: auto;
159 | }
160 | .menu-item-tile .menu-item-price {
161 | text-align: center;
162 | }
163 | .menu-item-description {
164 | text-align: center;;
165 | }
166 | }
167 |
168 |
169 | /********** Super extra small devices Only :-) (e.g., iPhone 4) **********/
170 | @media (max-width: 479px) {
171 | /* Home page */
172 | #menu-tile, #specials-tile {
173 | width: 280px;
174 | margin: 0 auto 15px;
175 | }
176 |
177 | .col-xxs-12 {
178 | position: relative;
179 | min-height: 1px;
180 | padding-right: 15px;
181 | padding-left: 15px;
182 | float: left;
183 | width: 100%;
184 | }
185 | }
186 |
--------------------------------------------------------------------------------
/Module5/css/restaurant.css:
--------------------------------------------------------------------------------
1 | body {
2 | font-size: 16px;
3 | color: #fff;
4 | background-color: #61122f;
5 | font-family: 'Oxygen', sans-serif;
6 | }
7 |
8 | .initial-loading {
9 | margin-top: 60px;
10 | }
11 |
12 | /** HEADER **/
13 | #header-nav {
14 | background-color: #f6b319;
15 | border-radius: 0;
16 | border: 0;
17 | }
18 |
19 | #logo-img {
20 | background: url('../images/restaurant-logo_large.png') no-repeat;
21 | width: 150px;
22 | height: 150px;
23 | margin: 10px 15px 10px 0;
24 | }
25 |
26 | .navbar-brand {
27 | padding-top: 25px;
28 | }
29 | .navbar-brand h1 { /* Restaurant name */
30 | font-family: 'Lora', serif;
31 | color: #557c3e;
32 | font-size: 1.5em;
33 | text-transform: uppercase;
34 | font-weight: bold;
35 | text-shadow: 1px 1px 1px #222;
36 | margin-top: 0;
37 | margin-bottom: 0;
38 | line-height: .75;
39 | }
40 | .navbar-brand a:hover, .navbar-brand a:focus {
41 | text-decoration: none;
42 | }
43 | .navbar-brand p { /* Kosher cert */
44 | color: #000;
45 | text-transform: uppercase;
46 | font-size: .7em;
47 | margin-top: 15px;
48 | }
49 | .navbar-brand p span { /* Star-K */
50 | vertical-align: middle;
51 | }
52 |
53 | #nav-list {
54 | margin-top: 10px;
55 | }
56 | #nav-list a {
57 | color: #951C49;
58 | text-align: center;
59 | }
60 | #nav-list a:hover {
61 | background: #E7E7E7;
62 | }
63 | #nav-list a span {
64 | font-size: 1.8em;
65 | }
66 |
67 | #phone {
68 | margin-top: 5px;
69 | }
70 | #phone a { /* Phone number */
71 | text-align: right;
72 | padding-bottom: 0;
73 | }
74 | #phone div { /* We Deliver */
75 | color: #557c3e;
76 | text-align: right;
77 | padding-right: 15px;
78 | }
79 |
80 | .navbar-header button.navbar-toggle, .navbar-header .icon-bar {
81 | border: 1px solid #61122f;
82 | }
83 | .navbar-header button.navbar-toggle {
84 | clear: both;
85 | margin-top: -30px;
86 | }
87 | /* END HEADER */
88 |
89 | /* FOOTER */
90 | .panel-footer {
91 | margin-top: 30px;
92 | padding-top: 35px;
93 | padding-bottom: 30px;
94 | background-color: #222;
95 | border-top: 0;
96 | }
97 | .panel-footer div.row {
98 | margin-bottom: 35px;
99 | }
100 | #hours, #address {
101 | line-height: 2;
102 | }
103 | #hours > span, #address > span {
104 | font-size: 1.3em;
105 | }
106 | #address p {
107 | color: #557c3e;
108 | font-size: .8em;
109 | line-height: 1.8;
110 | }
111 | #testimonials {
112 | font-style: italic;
113 | }
114 | #testimonials p:nth-child(2) {
115 | margin-top: 25px;
116 | }
117 | a[ui-sref="admin.auth"] {
118 | color: #fff;
119 | }
120 | /* END FOOTER */
121 |
122 | /********** Medium devices only **********/
123 | @media (min-width: 992px) and (max-width: 1199px) {
124 | /* Header */
125 | #logo-img {
126 | background: url('../images/restaurant-logo_medium.png') no-repeat;
127 | width: 100px;
128 | height: 100px;
129 | margin: 5px 5px 5px 0;
130 | }
131 | /* End Header */
132 | }
133 |
134 |
135 | /********** Extra small devices only **********/
136 | @media (max-width: 767px) {
137 | /* Header */
138 | .navbar-brand {
139 | padding-top: 10px;
140 | height: 80px;
141 | }
142 | .navbar-brand h1 { /* Restaurant name */
143 | padding-top: 10px;
144 | font-size: 5vw; /* 1vw = 1% of viewport width */
145 | }
146 | .navbar-brand p { /* Kosher cert */
147 | font-size: .6em;
148 | margin-top: 12px;
149 | }
150 | .navbar-brand p img { /* Star-K */
151 | height: 20px;
152 | }
153 |
154 | #collapsable-nav a { /* Collapsed nav menu text */
155 | font-size: 1.2em;
156 | }
157 | #collapsable-nav a span { /* Collapsed nav menu glyph */
158 | font-size: 1em;
159 | margin-right: 5px;
160 | }
161 |
162 | #call-btn > a {
163 | font-size: 1.5em;
164 | display: block;
165 | margin: 0 20px;
166 | padding: 10px;
167 | border: 2px solid #fff;
168 | background-color: #f6b319;
169 | color: #951c49;
170 | }
171 | #xs-deliver {
172 | margin-top: 5px;
173 | font-size: .7em;
174 | letter-spacing: .1em;
175 | text-transform: uppercase;
176 | }
177 | /* End Header */
178 |
179 | /* Footer */
180 | .panel-footer section {
181 | margin-bottom: 30px;
182 | text-align: center;
183 | }
184 | .panel-footer section:nth-child(3) {
185 | margin-bottom: 0; /* margin already exists on the whole row */
186 | }
187 | .panel-footer section hr {
188 | width: 50%;
189 | }
190 | /* End Footer */
191 | }
192 |
193 |
194 | /********** Super extra small devices Only :-) (e.g., iPhone 4) **********/
195 | @media (max-width: 479px) {
196 | /* Header */
197 | .navbar-brand h1 { /* Restaurant name */
198 | padding-top: 5px;
199 | font-size: 6vw;
200 | }
201 | /* End Header */
202 | }
203 |
--------------------------------------------------------------------------------
/Module5/lib/jasmine-2.4.1/boot.js:
--------------------------------------------------------------------------------
1 | /**
2 | Starting with version 2.0, this file "boots" Jasmine, performing all of the necessary initialization before executing the loaded environment and all of a project's specs. This file should be loaded after `jasmine.js` and `jasmine_html.js`, but before any project source files or spec files are loaded. Thus this file can also be used to customize Jasmine for a project.
3 |
4 | If a project is using Jasmine via the standalone distribution, this file can be customized directly. If a project is using Jasmine via the [Ruby gem][jasmine-gem], this file can be copied into the support directory via `jasmine copy_boot_js`. Other environments (e.g., Python) will have different mechanisms.
5 |
6 | The location of `boot.js` can be specified and/or overridden in `jasmine.yml`.
7 |
8 | [jasmine-gem]: http://github.com/pivotal/jasmine-gem
9 | */
10 |
11 | (function() {
12 |
13 | /**
14 | * ## Require & Instantiate
15 | *
16 | * Require Jasmine's core files. Specifically, this requires and attaches all of Jasmine's code to the `jasmine` reference.
17 | */
18 | window.jasmine = jasmineRequire.core(jasmineRequire);
19 |
20 | /**
21 | * Since this is being run in a browser and the results should populate to an HTML page, require the HTML-specific Jasmine code, injecting the same reference.
22 | */
23 | jasmineRequire.html(jasmine);
24 |
25 | /**
26 | * Create the Jasmine environment. This is used to run all specs in a project.
27 | */
28 | var env = jasmine.getEnv();
29 |
30 | /**
31 | * ## The Global Interface
32 | *
33 | * Build up the functions that will be exposed as the Jasmine public interface. A project can customize, rename or alias any of these functions as desired, provided the implementation remains unchanged.
34 | */
35 | var jasmineInterface = jasmineRequire.interface(jasmine, env);
36 |
37 | /**
38 | * Add all of the Jasmine global/public interface to the global scope, so a project can use the public interface directly. For example, calling `describe` in specs instead of `jasmine.getEnv().describe`.
39 | */
40 | extend(window, jasmineInterface);
41 |
42 | /**
43 | * ## Runner Parameters
44 | *
45 | * More browser specific code - wrap the query string in an object and to allow for getting/setting parameters from the runner user interface.
46 | */
47 |
48 | var queryString = new jasmine.QueryString({
49 | getWindowLocation: function() { return window.location; }
50 | });
51 |
52 | var catchingExceptions = queryString.getParam("catch");
53 | env.catchExceptions(typeof catchingExceptions === "undefined" ? true : catchingExceptions);
54 |
55 | var throwingExpectationFailures = queryString.getParam("throwFailures");
56 | env.throwOnExpectationFailure(throwingExpectationFailures);
57 |
58 | var random = queryString.getParam("random");
59 | env.randomizeTests(random);
60 |
61 | var seed = queryString.getParam("seed");
62 | if (seed) {
63 | env.seed(seed);
64 | }
65 |
66 | /**
67 | * ## Reporters
68 | * The `HtmlReporter` builds all of the HTML UI for the runner page. This reporter paints the dots, stars, and x's for specs, as well as all spec names and all failures (if any).
69 | */
70 | var htmlReporter = new jasmine.HtmlReporter({
71 | env: env,
72 | onRaiseExceptionsClick: function() { queryString.navigateWithNewParam("catch", !env.catchingExceptions()); },
73 | onThrowExpectationsClick: function() { queryString.navigateWithNewParam("throwFailures", !env.throwingExpectationFailures()); },
74 | onRandomClick: function() { queryString.navigateWithNewParam("random", !env.randomTests()); },
75 | addToExistingQueryString: function(key, value) { return queryString.fullStringWithNewParam(key, value); },
76 | getContainer: function() { return document.body; },
77 | createElement: function() { return document.createElement.apply(document, arguments); },
78 | createTextNode: function() { return document.createTextNode.apply(document, arguments); },
79 | timer: new jasmine.Timer()
80 | });
81 |
82 | /**
83 | * The `jsApiReporter` also receives spec results, and is used by any environment that needs to extract the results from JavaScript.
84 | */
85 | env.addReporter(jasmineInterface.jsApiReporter);
86 | env.addReporter(htmlReporter);
87 |
88 | /**
89 | * Filter which specs will be run by matching the start of the full name against the `spec` query param.
90 | */
91 | var specFilter = new jasmine.HtmlSpecFilter({
92 | filterString: function() { return queryString.getParam("spec"); }
93 | });
94 |
95 | env.specFilter = function(spec) {
96 | return specFilter.matches(spec.getFullName());
97 | };
98 |
99 | /**
100 | * Setting up timing functions to be able to be overridden. Certain browsers (Safari, IE 8, phantomjs) require this hack.
101 | */
102 | window.setTimeout = window.setTimeout;
103 | window.setInterval = window.setInterval;
104 | window.clearTimeout = window.clearTimeout;
105 | window.clearInterval = window.clearInterval;
106 |
107 | /**
108 | * ## Execution
109 | *
110 | * Replace the browser window's `onload`, ensure it's called, and then run all of the loaded specs. This includes initializing the `HtmlReporter` instance and then executing the loaded Jasmine environment. All of this will happen after all of the specs are loaded.
111 | */
112 | var currentWindowOnload = window.onload;
113 |
114 | window.onload = function() {
115 | if (currentWindowOnload) {
116 | currentWindowOnload();
117 | }
118 | htmlReporter.initialize();
119 | env.execute();
120 | };
121 |
122 | /**
123 | * Helper function for readability above.
124 | */
125 | function extend(destination, source) {
126 | for (var property in source) destination[property] = source[property];
127 | return destination;
128 | }
129 |
130 | }());
131 |
--------------------------------------------------------------------------------
/Module5/lib/jasmine-2.4.1/console.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2008-2015 Pivotal Labs
3 |
4 | Permission is hereby granted, free of charge, to any person obtaining
5 | a copy of this software and associated documentation files (the
6 | "Software"), to deal in the Software without restriction, including
7 | without limitation the rights to use, copy, modify, merge, publish,
8 | distribute, sublicense, and/or sell copies of the Software, and to
9 | permit persons to whom the Software is furnished to do so, subject to
10 | the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be
13 | included in all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 | */
23 | function getJasmineRequireObj() {
24 | if (typeof module !== 'undefined' && module.exports) {
25 | return exports;
26 | } else {
27 | window.jasmineRequire = window.jasmineRequire || {};
28 | return window.jasmineRequire;
29 | }
30 | }
31 |
32 | getJasmineRequireObj().console = function(jRequire, j$) {
33 | j$.ConsoleReporter = jRequire.ConsoleReporter();
34 | };
35 |
36 | getJasmineRequireObj().ConsoleReporter = function() {
37 |
38 | var noopTimer = {
39 | start: function(){},
40 | elapsed: function(){ return 0; }
41 | };
42 |
43 | function ConsoleReporter(options) {
44 | var print = options.print,
45 | showColors = options.showColors || false,
46 | onComplete = options.onComplete || function() {},
47 | timer = options.timer || noopTimer,
48 | specCount,
49 | failureCount,
50 | failedSpecs = [],
51 | pendingCount,
52 | ansi = {
53 | green: '\x1B[32m',
54 | red: '\x1B[31m',
55 | yellow: '\x1B[33m',
56 | none: '\x1B[0m'
57 | },
58 | failedSuites = [];
59 |
60 | print('ConsoleReporter is deprecated and will be removed in a future version.');
61 |
62 | this.jasmineStarted = function() {
63 | specCount = 0;
64 | failureCount = 0;
65 | pendingCount = 0;
66 | print('Started');
67 | printNewline();
68 | timer.start();
69 | };
70 |
71 | this.jasmineDone = function() {
72 | printNewline();
73 | for (var i = 0; i < failedSpecs.length; i++) {
74 | specFailureDetails(failedSpecs[i]);
75 | }
76 |
77 | if(specCount > 0) {
78 | printNewline();
79 |
80 | var specCounts = specCount + ' ' + plural('spec', specCount) + ', ' +
81 | failureCount + ' ' + plural('failure', failureCount);
82 |
83 | if (pendingCount) {
84 | specCounts += ', ' + pendingCount + ' pending ' + plural('spec', pendingCount);
85 | }
86 |
87 | print(specCounts);
88 | } else {
89 | print('No specs found');
90 | }
91 |
92 | printNewline();
93 | var seconds = timer.elapsed() / 1000;
94 | print('Finished in ' + seconds + ' ' + plural('second', seconds));
95 | printNewline();
96 |
97 | for(i = 0; i < failedSuites.length; i++) {
98 | suiteFailureDetails(failedSuites[i]);
99 | }
100 |
101 | onComplete(failureCount === 0);
102 | };
103 |
104 | this.specDone = function(result) {
105 | specCount++;
106 |
107 | if (result.status == 'pending') {
108 | pendingCount++;
109 | print(colored('yellow', '*'));
110 | return;
111 | }
112 |
113 | if (result.status == 'passed') {
114 | print(colored('green', '.'));
115 | return;
116 | }
117 |
118 | if (result.status == 'failed') {
119 | failureCount++;
120 | failedSpecs.push(result);
121 | print(colored('red', 'F'));
122 | }
123 | };
124 |
125 | this.suiteDone = function(result) {
126 | if (result.failedExpectations && result.failedExpectations.length > 0) {
127 | failureCount++;
128 | failedSuites.push(result);
129 | }
130 | };
131 |
132 | return this;
133 |
134 | function printNewline() {
135 | print('\n');
136 | }
137 |
138 | function colored(color, str) {
139 | return showColors ? (ansi[color] + str + ansi.none) : str;
140 | }
141 |
142 | function plural(str, count) {
143 | return count == 1 ? str : str + 's';
144 | }
145 |
146 | function repeat(thing, times) {
147 | var arr = [];
148 | for (var i = 0; i < times; i++) {
149 | arr.push(thing);
150 | }
151 | return arr;
152 | }
153 |
154 | function indent(str, spaces) {
155 | var lines = (str || '').split('\n');
156 | var newArr = [];
157 | for (var i = 0; i < lines.length; i++) {
158 | newArr.push(repeat(' ', spaces).join('') + lines[i]);
159 | }
160 | return newArr.join('\n');
161 | }
162 |
163 | function specFailureDetails(result) {
164 | printNewline();
165 | print(result.fullName);
166 |
167 | for (var i = 0; i < result.failedExpectations.length; i++) {
168 | var failedExpectation = result.failedExpectations[i];
169 | printNewline();
170 | print(indent(failedExpectation.message, 2));
171 | print(indent(failedExpectation.stack, 2));
172 | }
173 |
174 | printNewline();
175 | }
176 |
177 | function suiteFailureDetails(result) {
178 | for (var i = 0; i < result.failedExpectations.length; i++) {
179 | printNewline();
180 | print(colored('red', 'An error was thrown in an afterAll'));
181 | printNewline();
182 | print(colored('red', 'AfterAll ' + result.failedExpectations[i].message));
183 |
184 | }
185 | printNewline();
186 | }
187 | }
188 |
189 | return ConsoleReporter;
190 | };
191 |
--------------------------------------------------------------------------------
/Module5/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | David Chu's China Bistro
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
70 |
71 |
77 | * We Deliver
78 |
79 |
80 |
81 |
Loading Site...
82 |
83 |
84 |
85 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
--------------------------------------------------------------------------------
/Module5/lib/ng-file-upload/ng-file-upload-shim.min.js:
--------------------------------------------------------------------------------
1 | /*! 12.0.4 */
2 | !function(){function a(a,b){window.XMLHttpRequest.prototype[a]=b(window.XMLHttpRequest.prototype[a])}function b(a,b,c){try{Object.defineProperty(a,b,{get:c})}catch(d){}}if(window.FileAPI||(window.FileAPI={}),!window.XMLHttpRequest)throw"AJAX is not supported. XMLHttpRequest is not defined.";if(FileAPI.shouldLoad=!window.FormData||FileAPI.forceLoad,FileAPI.shouldLoad){var c=function(a){if(!a.__listeners){a.upload||(a.upload={}),a.__listeners=[];var b=a.upload.addEventListener;a.upload.addEventListener=function(c,d){a.__listeners[c]=d,b&&b.apply(this,arguments)}}};a("open",function(a){return function(b,d,e){c(this),this.__url=d;try{a.apply(this,[b,d,e])}catch(f){f.message.indexOf("Access is denied")>-1&&(this.__origError=f,a.apply(this,[b,"_fix_for_ie_crossdomain__",e]))}}}),a("getResponseHeader",function(a){return function(b){return this.__fileApiXHR&&this.__fileApiXHR.getResponseHeader?this.__fileApiXHR.getResponseHeader(b):null==a?null:a.apply(this,[b])}}),a("getAllResponseHeaders",function(a){return function(){return this.__fileApiXHR&&this.__fileApiXHR.getAllResponseHeaders?this.__fileApiXHR.getAllResponseHeaders():null==a?null:a.apply(this)}}),a("abort",function(a){return function(){return this.__fileApiXHR&&this.__fileApiXHR.abort?this.__fileApiXHR.abort():null==a?null:a.apply(this)}}),a("setRequestHeader",function(a){return function(b,d){if("__setXHR_"===b){c(this);var e=d(this);e instanceof Function&&e(this)}else this.__requestHeaders=this.__requestHeaders||{},this.__requestHeaders[b]=d,a.apply(this,arguments)}}),a("send",function(a){return function(){var c=this;if(arguments[0]&&arguments[0].__isFileAPIShim){var d=arguments[0],e={url:c.__url,jsonp:!1,cache:!0,complete:function(a,d){a&&angular.isString(a)&&-1!==a.indexOf("#2174")&&(a=null),c.__completed=!0,!a&&c.__listeners.load&&c.__listeners.load({type:"load",loaded:c.__loaded,total:c.__total,target:c,lengthComputable:!0}),!a&&c.__listeners.loadend&&c.__listeners.loadend({type:"loadend",loaded:c.__loaded,total:c.__total,target:c,lengthComputable:!0}),"abort"===a&&c.__listeners.abort&&c.__listeners.abort({type:"abort",loaded:c.__loaded,total:c.__total,target:c,lengthComputable:!0}),void 0!==d.status&&b(c,"status",function(){return 0===d.status&&a&&"abort"!==a?500:d.status}),void 0!==d.statusText&&b(c,"statusText",function(){return d.statusText}),b(c,"readyState",function(){return 4}),void 0!==d.response&&b(c,"response",function(){return d.response});var e=d.responseText||(a&&0===d.status&&"abort"!==a?a:void 0);b(c,"responseText",function(){return e}),b(c,"response",function(){return e}),a&&b(c,"err",function(){return a}),c.__fileApiXHR=d,c.onreadystatechange&&c.onreadystatechange(),c.onload&&c.onload()},progress:function(a){if(a.target=c,c.__listeners.progress&&c.__listeners.progress(a),c.__total=a.total,c.__loaded=a.loaded,a.total===a.loaded){var b=this;setTimeout(function(){c.__completed||(c.getAllResponseHeaders=function(){},b.complete(null,{status:204,statusText:"No Content"}))},FileAPI.noContentTimeout||1e4)}},headers:c.__requestHeaders};e.data={},e.files={};for(var f=0;f-1){e=h.substring(0,g+1);break}null==FileAPI.staticPath&&(FileAPI.staticPath=e),i.setAttribute("src",d||e+"FileAPI.min.js"),document.getElementsByTagName("head")[0].appendChild(i)}FileAPI.ngfFixIE=function(d,e,f){if(!b())throw'Adode Flash Player need to be installed. To check ahead use "FileAPI.hasFlash"';var g=function(){var b=e.parent();d.attr("disabled")?b&&b.removeClass("js-fileapi-wrapper"):(e.attr("__ngf_flash_")||(e.unbind("change"),e.unbind("click"),e.bind("change",function(a){h.apply(this,[a]),f.apply(this,[a])}),e.attr("__ngf_flash_","true")),b.addClass("js-fileapi-wrapper"),a(d)||(b.css("position","absolute").css("top",c(d[0]).top+"px").css("left",c(d[0]).left+"px").css("width",d[0].offsetWidth+"px").css("height",d[0].offsetHeight+"px").css("filter","alpha(opacity=0)").css("display",d.css("display")).css("overflow","hidden").css("z-index","900000").css("visibility","visible"),e.css("width",d[0].offsetWidth+"px").css("height",d[0].offsetHeight+"px").css("position","absolute").css("top","0px").css("left","0px")))};d.bind("mouseenter",g);var h=function(a){for(var b=FileAPI.getFiles(a),c=0;c
6 | * @version 12.0.4
7 | */
8 |
9 | (function () {
10 | /** @namespace FileAPI.noContentTimeout */
11 |
12 | function patchXHR(fnName, newFn) {
13 | window.XMLHttpRequest.prototype[fnName] = newFn(window.XMLHttpRequest.prototype[fnName]);
14 | }
15 |
16 | function redefineProp(xhr, prop, fn) {
17 | try {
18 | Object.defineProperty(xhr, prop, {get: fn});
19 | } catch (e) {/*ignore*/
20 | }
21 | }
22 |
23 | if (!window.FileAPI) {
24 | window.FileAPI = {};
25 | }
26 |
27 | if (!window.XMLHttpRequest) {
28 | throw 'AJAX is not supported. XMLHttpRequest is not defined.';
29 | }
30 |
31 | FileAPI.shouldLoad = !window.FormData || FileAPI.forceLoad;
32 | if (FileAPI.shouldLoad) {
33 | var initializeUploadListener = function (xhr) {
34 | if (!xhr.__listeners) {
35 | if (!xhr.upload) xhr.upload = {};
36 | xhr.__listeners = [];
37 | var origAddEventListener = xhr.upload.addEventListener;
38 | xhr.upload.addEventListener = function (t, fn) {
39 | xhr.__listeners[t] = fn;
40 | if (origAddEventListener) origAddEventListener.apply(this, arguments);
41 | };
42 | }
43 | };
44 |
45 | patchXHR('open', function (orig) {
46 | return function (m, url, b) {
47 | initializeUploadListener(this);
48 | this.__url = url;
49 | try {
50 | orig.apply(this, [m, url, b]);
51 | } catch (e) {
52 | if (e.message.indexOf('Access is denied') > -1) {
53 | this.__origError = e;
54 | orig.apply(this, [m, '_fix_for_ie_crossdomain__', b]);
55 | }
56 | }
57 | };
58 | });
59 |
60 | patchXHR('getResponseHeader', function (orig) {
61 | return function (h) {
62 | return this.__fileApiXHR && this.__fileApiXHR.getResponseHeader ? this.__fileApiXHR.getResponseHeader(h) : (orig == null ? null : orig.apply(this, [h]));
63 | };
64 | });
65 |
66 | patchXHR('getAllResponseHeaders', function (orig) {
67 | return function () {
68 | return this.__fileApiXHR && this.__fileApiXHR.getAllResponseHeaders ? this.__fileApiXHR.getAllResponseHeaders() : (orig == null ? null : orig.apply(this));
69 | };
70 | });
71 |
72 | patchXHR('abort', function (orig) {
73 | return function () {
74 | return this.__fileApiXHR && this.__fileApiXHR.abort ? this.__fileApiXHR.abort() : (orig == null ? null : orig.apply(this));
75 | };
76 | });
77 |
78 | patchXHR('setRequestHeader', function (orig) {
79 | return function (header, value) {
80 | if (header === '__setXHR_') {
81 | initializeUploadListener(this);
82 | var val = value(this);
83 | // fix for angular < 1.2.0
84 | if (val instanceof Function) {
85 | val(this);
86 | }
87 | } else {
88 | this.__requestHeaders = this.__requestHeaders || {};
89 | this.__requestHeaders[header] = value;
90 | orig.apply(this, arguments);
91 | }
92 | };
93 | });
94 |
95 | patchXHR('send', function (orig) {
96 | return function () {
97 | var xhr = this;
98 | if (arguments[0] && arguments[0].__isFileAPIShim) {
99 | var formData = arguments[0];
100 | var config = {
101 | url: xhr.__url,
102 | jsonp: false, //removes the callback form param
103 | cache: true, //removes the ?fileapiXXX in the url
104 | complete: function (err, fileApiXHR) {
105 | if (err && angular.isString(err) && err.indexOf('#2174') !== -1) {
106 | // this error seems to be fine the file is being uploaded properly.
107 | err = null;
108 | }
109 | xhr.__completed = true;
110 | if (!err && xhr.__listeners.load)
111 | xhr.__listeners.load({
112 | type: 'load',
113 | loaded: xhr.__loaded,
114 | total: xhr.__total,
115 | target: xhr,
116 | lengthComputable: true
117 | });
118 | if (!err && xhr.__listeners.loadend)
119 | xhr.__listeners.loadend({
120 | type: 'loadend',
121 | loaded: xhr.__loaded,
122 | total: xhr.__total,
123 | target: xhr,
124 | lengthComputable: true
125 | });
126 | if (err === 'abort' && xhr.__listeners.abort)
127 | xhr.__listeners.abort({
128 | type: 'abort',
129 | loaded: xhr.__loaded,
130 | total: xhr.__total,
131 | target: xhr,
132 | lengthComputable: true
133 | });
134 | if (fileApiXHR.status !== undefined) redefineProp(xhr, 'status', function () {
135 | return (fileApiXHR.status === 0 && err && err !== 'abort') ? 500 : fileApiXHR.status;
136 | });
137 | if (fileApiXHR.statusText !== undefined) redefineProp(xhr, 'statusText', function () {
138 | return fileApiXHR.statusText;
139 | });
140 | redefineProp(xhr, 'readyState', function () {
141 | return 4;
142 | });
143 | if (fileApiXHR.response !== undefined) redefineProp(xhr, 'response', function () {
144 | return fileApiXHR.response;
145 | });
146 | var resp = fileApiXHR.responseText || (err && fileApiXHR.status === 0 && err !== 'abort' ? err : undefined);
147 | redefineProp(xhr, 'responseText', function () {
148 | return resp;
149 | });
150 | redefineProp(xhr, 'response', function () {
151 | return resp;
152 | });
153 | if (err) redefineProp(xhr, 'err', function () {
154 | return err;
155 | });
156 | xhr.__fileApiXHR = fileApiXHR;
157 | if (xhr.onreadystatechange) xhr.onreadystatechange();
158 | if (xhr.onload) xhr.onload();
159 | },
160 | progress: function (e) {
161 | e.target = xhr;
162 | if (xhr.__listeners.progress) xhr.__listeners.progress(e);
163 | xhr.__total = e.total;
164 | xhr.__loaded = e.loaded;
165 | if (e.total === e.loaded) {
166 | // fix flash issue that doesn't call complete if there is no response text from the server
167 | var _this = this;
168 | setTimeout(function () {
169 | if (!xhr.__completed) {
170 | xhr.getAllResponseHeaders = function () {
171 | };
172 | _this.complete(null, {status: 204, statusText: 'No Content'});
173 | }
174 | }, FileAPI.noContentTimeout || 10000);
175 | }
176 | },
177 | headers: xhr.__requestHeaders
178 | };
179 | config.data = {};
180 | config.files = {};
181 | for (var i = 0; i < formData.data.length; i++) {
182 | var item = formData.data[i];
183 | if (item.val != null && item.val.name != null && item.val.size != null && item.val.type != null) {
184 | config.files[item.key] = item.val;
185 | } else {
186 | config.data[item.key] = item.val;
187 | }
188 | }
189 |
190 | setTimeout(function () {
191 | if (!FileAPI.hasFlash) {
192 | throw 'Adode Flash Player need to be installed. To check ahead use "FileAPI.hasFlash"';
193 | }
194 | xhr.__fileApiXHR = FileAPI.upload(config);
195 | }, 1);
196 | } else {
197 | if (this.__origError) {
198 | throw this.__origError;
199 | }
200 | orig.apply(xhr, arguments);
201 | }
202 | };
203 | });
204 | window.XMLHttpRequest.__isFileAPIShim = true;
205 | window.FormData = FormData = function () {
206 | return {
207 | append: function (key, val, name) {
208 | if (val.__isFileAPIBlobShim) {
209 | val = val.data[0];
210 | }
211 | this.data.push({
212 | key: key,
213 | val: val,
214 | name: name
215 | });
216 | },
217 | data: [],
218 | __isFileAPIShim: true
219 | };
220 | };
221 |
222 | window.Blob = Blob = function (b) {
223 | return {
224 | data: b,
225 | __isFileAPIBlobShim: true
226 | };
227 | };
228 | }
229 |
230 | })();
231 |
232 | (function () {
233 | /** @namespace FileAPI.forceLoad */
234 | /** @namespace window.FileAPI.jsUrl */
235 | /** @namespace window.FileAPI.jsPath */
236 |
237 | function isInputTypeFile(elem) {
238 | return elem[0].tagName.toLowerCase() === 'input' && elem.attr('type') && elem.attr('type').toLowerCase() === 'file';
239 | }
240 |
241 | function hasFlash() {
242 | try {
243 | var fo = new ActiveXObject('ShockwaveFlash.ShockwaveFlash');
244 | if (fo) return true;
245 | } catch (e) {
246 | if (navigator.mimeTypes['application/x-shockwave-flash'] !== undefined) return true;
247 | }
248 | return false;
249 | }
250 |
251 | function getOffset(obj) {
252 | var left = 0, top = 0;
253 |
254 | if (window.jQuery) {
255 | return jQuery(obj).offset();
256 | }
257 |
258 | if (obj.offsetParent) {
259 | do {
260 | left += (obj.offsetLeft - obj.scrollLeft);
261 | top += (obj.offsetTop - obj.scrollTop);
262 | obj = obj.offsetParent;
263 | } while (obj);
264 | }
265 | return {
266 | left: left,
267 | top: top
268 | };
269 | }
270 |
271 | if (FileAPI.shouldLoad) {
272 | FileAPI.hasFlash = hasFlash();
273 |
274 | //load FileAPI
275 | if (FileAPI.forceLoad) {
276 | FileAPI.html5 = false;
277 | }
278 |
279 | if (!FileAPI.upload) {
280 | var jsUrl, basePath, script = document.createElement('script'), allScripts = document.getElementsByTagName('script'), i, index, src;
281 | if (window.FileAPI.jsUrl) {
282 | jsUrl = window.FileAPI.jsUrl;
283 | } else if (window.FileAPI.jsPath) {
284 | basePath = window.FileAPI.jsPath;
285 | } else {
286 | for (i = 0; i < allScripts.length; i++) {
287 | src = allScripts[i].src;
288 | index = src.search(/\/ng\-file\-upload[\-a-zA-z0-9\.]*\.js/);
289 | if (index > -1) {
290 | basePath = src.substring(0, index + 1);
291 | break;
292 | }
293 | }
294 | }
295 |
296 | if (FileAPI.staticPath == null) FileAPI.staticPath = basePath;
297 | script.setAttribute('src', jsUrl || basePath + 'FileAPI.min.js');
298 | document.getElementsByTagName('head')[0].appendChild(script);
299 | }
300 |
301 | FileAPI.ngfFixIE = function (elem, fileElem, changeFn) {
302 | if (!hasFlash()) {
303 | throw 'Adode Flash Player need to be installed. To check ahead use "FileAPI.hasFlash"';
304 | }
305 | var fixInputStyle = function () {
306 | var label = fileElem.parent();
307 | if (elem.attr('disabled')) {
308 | if (label) label.removeClass('js-fileapi-wrapper');
309 | } else {
310 | if (!fileElem.attr('__ngf_flash_')) {
311 | fileElem.unbind('change');
312 | fileElem.unbind('click');
313 | fileElem.bind('change', function (evt) {
314 | fileApiChangeFn.apply(this, [evt]);
315 | changeFn.apply(this, [evt]);
316 | });
317 | fileElem.attr('__ngf_flash_', 'true');
318 | }
319 | label.addClass('js-fileapi-wrapper');
320 | if (!isInputTypeFile(elem)) {
321 | label.css('position', 'absolute')
322 | .css('top', getOffset(elem[0]).top + 'px').css('left', getOffset(elem[0]).left + 'px')
323 | .css('width', elem[0].offsetWidth + 'px').css('height', elem[0].offsetHeight + 'px')
324 | .css('filter', 'alpha(opacity=0)').css('display', elem.css('display'))
325 | .css('overflow', 'hidden').css('z-index', '900000')
326 | .css('visibility', 'visible');
327 | fileElem.css('width', elem[0].offsetWidth + 'px').css('height', elem[0].offsetHeight + 'px')
328 | .css('position', 'absolute').css('top', '0px').css('left', '0px');
329 | }
330 | }
331 | };
332 |
333 | elem.bind('mouseenter', fixInputStyle);
334 |
335 | var fileApiChangeFn = function (evt) {
336 | var files = FileAPI.getFiles(evt);
337 | //just a double check for #233
338 | for (var i = 0; i < files.length; i++) {
339 | if (files[i].size === undefined) files[i].size = 0;
340 | if (files[i].name === undefined) files[i].name = 'file';
341 | if (files[i].type === undefined) files[i].type = 'undefined';
342 | }
343 | if (!evt.target) {
344 | evt.target = {};
345 | }
346 | evt.target.files = files;
347 | // if evt.target.files is not writable use helper field
348 | if (evt.target.files !== files) {
349 | evt.__files_ = files;
350 | }
351 | (evt.__files_ || evt.target.files).item = function (i) {
352 | return (evt.__files_ || evt.target.files)[i] || null;
353 | };
354 | };
355 | };
356 |
357 | FileAPI.disableFileInput = function (elem, disable) {
358 | if (disable) {
359 | elem.removeClass('js-fileapi-wrapper');
360 | } else {
361 | elem.addClass('js-fileapi-wrapper');
362 | }
363 | };
364 | }
365 | })();
366 |
367 | if (!window.FileReader) {
368 | window.FileReader = function () {
369 | var _this = this, loadStarted = false;
370 | this.listeners = {};
371 | this.addEventListener = function (type, fn) {
372 | _this.listeners[type] = _this.listeners[type] || [];
373 | _this.listeners[type].push(fn);
374 | };
375 | this.removeEventListener = function (type, fn) {
376 | if (_this.listeners[type]) _this.listeners[type].splice(_this.listeners[type].indexOf(fn), 1);
377 | };
378 | this.dispatchEvent = function (evt) {
379 | var list = _this.listeners[evt.type];
380 | if (list) {
381 | for (var i = 0; i < list.length; i++) {
382 | list[i].call(_this, evt);
383 | }
384 | }
385 | };
386 | this.onabort = this.onerror = this.onload = this.onloadstart = this.onloadend = this.onprogress = null;
387 |
388 | var constructEvent = function (type, evt) {
389 | var e = {type: type, target: _this, loaded: evt.loaded, total: evt.total, error: evt.error};
390 | if (evt.result != null) e.target.result = evt.result;
391 | return e;
392 | };
393 | var listener = function (evt) {
394 | if (!loadStarted) {
395 | loadStarted = true;
396 | if (_this.onloadstart) _this.onloadstart(constructEvent('loadstart', evt));
397 | }
398 | var e;
399 | if (evt.type === 'load') {
400 | if (_this.onloadend) _this.onloadend(constructEvent('loadend', evt));
401 | e = constructEvent('load', evt);
402 | if (_this.onload) _this.onload(e);
403 | _this.dispatchEvent(e);
404 | } else if (evt.type === 'progress') {
405 | e = constructEvent('progress', evt);
406 | if (_this.onprogress) _this.onprogress(e);
407 | _this.dispatchEvent(e);
408 | } else {
409 | e = constructEvent('error', evt);
410 | if (_this.onerror) _this.onerror(e);
411 | _this.dispatchEvent(e);
412 | }
413 | };
414 | this.readAsDataURL = function (file) {
415 | FileAPI.readAsDataURL(file, listener);
416 | };
417 | this.readAsText = function (file) {
418 | FileAPI.readAsText(file, listener);
419 | };
420 | };
421 | }
422 |
--------------------------------------------------------------------------------
/Module5/lib/jasmine-2.4.1/jasmine-html.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2008-2015 Pivotal Labs
3 |
4 | Permission is hereby granted, free of charge, to any person obtaining
5 | a copy of this software and associated documentation files (the
6 | "Software"), to deal in the Software without restriction, including
7 | without limitation the rights to use, copy, modify, merge, publish,
8 | distribute, sublicense, and/or sell copies of the Software, and to
9 | permit persons to whom the Software is furnished to do so, subject to
10 | the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be
13 | included in all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 | */
23 | jasmineRequire.html = function(j$) {
24 | j$.ResultsNode = jasmineRequire.ResultsNode();
25 | j$.HtmlReporter = jasmineRequire.HtmlReporter(j$);
26 | j$.QueryString = jasmineRequire.QueryString();
27 | j$.HtmlSpecFilter = jasmineRequire.HtmlSpecFilter();
28 | };
29 |
30 | jasmineRequire.HtmlReporter = function(j$) {
31 |
32 | var noopTimer = {
33 | start: function() {},
34 | elapsed: function() { return 0; }
35 | };
36 |
37 | function HtmlReporter(options) {
38 | var env = options.env || {},
39 | getContainer = options.getContainer,
40 | createElement = options.createElement,
41 | createTextNode = options.createTextNode,
42 | onRaiseExceptionsClick = options.onRaiseExceptionsClick || function() {},
43 | onThrowExpectationsClick = options.onThrowExpectationsClick || function() {},
44 | onRandomClick = options.onRandomClick || function() {},
45 | addToExistingQueryString = options.addToExistingQueryString || defaultQueryString,
46 | timer = options.timer || noopTimer,
47 | results = [],
48 | specsExecuted = 0,
49 | failureCount = 0,
50 | pendingSpecCount = 0,
51 | htmlReporterMain,
52 | symbols,
53 | failedSuites = [];
54 |
55 | this.initialize = function() {
56 | clearPrior();
57 | htmlReporterMain = createDom('div', {className: 'jasmine_html-reporter'},
58 | createDom('div', {className: 'jasmine-banner'},
59 | createDom('a', {className: 'jasmine-title', href: 'http://jasmine.github.io/', target: '_blank'}),
60 | createDom('span', {className: 'jasmine-version'}, j$.version)
61 | ),
62 | createDom('ul', {className: 'jasmine-symbol-summary'}),
63 | createDom('div', {className: 'jasmine-alert'}),
64 | createDom('div', {className: 'jasmine-results'},
65 | createDom('div', {className: 'jasmine-failures'})
66 | )
67 | );
68 | getContainer().appendChild(htmlReporterMain);
69 | };
70 |
71 | var totalSpecsDefined;
72 | this.jasmineStarted = function(options) {
73 | totalSpecsDefined = options.totalSpecsDefined || 0;
74 | timer.start();
75 | };
76 |
77 | var summary = createDom('div', {className: 'jasmine-summary'});
78 |
79 | var topResults = new j$.ResultsNode({}, '', null),
80 | currentParent = topResults;
81 |
82 | this.suiteStarted = function(result) {
83 | currentParent.addChild(result, 'suite');
84 | currentParent = currentParent.last();
85 | };
86 |
87 | this.suiteDone = function(result) {
88 | if (result.status == 'failed') {
89 | failedSuites.push(result);
90 | }
91 |
92 | if (currentParent == topResults) {
93 | return;
94 | }
95 |
96 | currentParent = currentParent.parent;
97 | };
98 |
99 | this.specStarted = function(result) {
100 | currentParent.addChild(result, 'spec');
101 | };
102 |
103 | var failures = [];
104 | this.specDone = function(result) {
105 | if(noExpectations(result) && typeof console !== 'undefined' && typeof console.error !== 'undefined') {
106 | console.error('Spec \'' + result.fullName + '\' has no expectations.');
107 | }
108 |
109 | if (result.status != 'disabled') {
110 | specsExecuted++;
111 | }
112 |
113 | if (!symbols){
114 | symbols = find('.jasmine-symbol-summary');
115 | }
116 |
117 | symbols.appendChild(createDom('li', {
118 | className: noExpectations(result) ? 'jasmine-empty' : 'jasmine-' + result.status,
119 | id: 'spec_' + result.id,
120 | title: result.fullName
121 | }
122 | ));
123 |
124 | if (result.status == 'failed') {
125 | failureCount++;
126 |
127 | var failure =
128 | createDom('div', {className: 'jasmine-spec-detail jasmine-failed'},
129 | createDom('div', {className: 'jasmine-description'},
130 | createDom('a', {title: result.fullName, href: specHref(result)}, result.fullName)
131 | ),
132 | createDom('div', {className: 'jasmine-messages'})
133 | );
134 | var messages = failure.childNodes[1];
135 |
136 | for (var i = 0; i < result.failedExpectations.length; i++) {
137 | var expectation = result.failedExpectations[i];
138 | messages.appendChild(createDom('div', {className: 'jasmine-result-message'}, expectation.message));
139 | messages.appendChild(createDom('div', {className: 'jasmine-stack-trace'}, expectation.stack));
140 | }
141 |
142 | failures.push(failure);
143 | }
144 |
145 | if (result.status == 'pending') {
146 | pendingSpecCount++;
147 | }
148 | };
149 |
150 | this.jasmineDone = function(doneResult) {
151 | var banner = find('.jasmine-banner');
152 | var alert = find('.jasmine-alert');
153 | var order = doneResult && doneResult.order;
154 | alert.appendChild(createDom('span', {className: 'jasmine-duration'}, 'finished in ' + timer.elapsed() / 1000 + 's'));
155 |
156 | banner.appendChild(
157 | createDom('div', { className: 'jasmine-run-options' },
158 | createDom('span', { className: 'jasmine-trigger' }, 'Options'),
159 | createDom('div', { className: 'jasmine-payload' },
160 | createDom('div', { className: 'jasmine-exceptions' },
161 | createDom('input', {
162 | className: 'jasmine-raise',
163 | id: 'jasmine-raise-exceptions',
164 | type: 'checkbox'
165 | }),
166 | createDom('label', { className: 'jasmine-label', 'for': 'jasmine-raise-exceptions' }, 'raise exceptions')),
167 | createDom('div', { className: 'jasmine-throw-failures' },
168 | createDom('input', {
169 | className: 'jasmine-throw',
170 | id: 'jasmine-throw-failures',
171 | type: 'checkbox'
172 | }),
173 | createDom('label', { className: 'jasmine-label', 'for': 'jasmine-throw-failures' }, 'stop spec on expectation failure')),
174 | createDom('div', { className: 'jasmine-random-order' },
175 | createDom('input', {
176 | className: 'jasmine-random',
177 | id: 'jasmine-random-order',
178 | type: 'checkbox'
179 | }),
180 | createDom('label', { className: 'jasmine-label', 'for': 'jasmine-random-order' }, 'run tests in random order'))
181 | )
182 | ));
183 |
184 | var raiseCheckbox = find('#jasmine-raise-exceptions');
185 |
186 | raiseCheckbox.checked = !env.catchingExceptions();
187 | raiseCheckbox.onclick = onRaiseExceptionsClick;
188 |
189 | var throwCheckbox = find('#jasmine-throw-failures');
190 | throwCheckbox.checked = env.throwingExpectationFailures();
191 | throwCheckbox.onclick = onThrowExpectationsClick;
192 |
193 | var randomCheckbox = find('#jasmine-random-order');
194 | randomCheckbox.checked = env.randomTests();
195 | randomCheckbox.onclick = onRandomClick;
196 |
197 | var optionsMenu = find('.jasmine-run-options'),
198 | optionsTrigger = optionsMenu.querySelector('.jasmine-trigger'),
199 | optionsPayload = optionsMenu.querySelector('.jasmine-payload'),
200 | isOpen = /\bjasmine-open\b/;
201 |
202 | optionsTrigger.onclick = function() {
203 | if (isOpen.test(optionsPayload.className)) {
204 | optionsPayload.className = optionsPayload.className.replace(isOpen, '');
205 | } else {
206 | optionsPayload.className += ' jasmine-open';
207 | }
208 | };
209 |
210 | if (specsExecuted < totalSpecsDefined) {
211 | var skippedMessage = 'Ran ' + specsExecuted + ' of ' + totalSpecsDefined + ' specs - run all';
212 | alert.appendChild(
213 | createDom('span', {className: 'jasmine-bar jasmine-skipped'},
214 | createDom('a', {href: '?', title: 'Run all specs'}, skippedMessage)
215 | )
216 | );
217 | }
218 | var statusBarMessage = '';
219 | var statusBarClassName = 'jasmine-bar ';
220 |
221 | if (totalSpecsDefined > 0) {
222 | statusBarMessage += pluralize('spec', specsExecuted) + ', ' + pluralize('failure', failureCount);
223 | if (pendingSpecCount) { statusBarMessage += ', ' + pluralize('pending spec', pendingSpecCount); }
224 | statusBarClassName += (failureCount > 0) ? 'jasmine-failed' : 'jasmine-passed';
225 | } else {
226 | statusBarClassName += 'jasmine-skipped';
227 | statusBarMessage += 'No specs found';
228 | }
229 |
230 | var seedBar;
231 | if (order && order.random) {
232 | seedBar = createDom('span', {className: 'jasmine-seed-bar'},
233 | ', randomized with seed ',
234 | createDom('a', {title: 'randomized with seed ' + order.seed, href: seedHref(order.seed)}, order.seed)
235 | );
236 | }
237 |
238 | alert.appendChild(createDom('span', {className: statusBarClassName}, statusBarMessage, seedBar));
239 |
240 | for(i = 0; i < failedSuites.length; i++) {
241 | var failedSuite = failedSuites[i];
242 | for(var j = 0; j < failedSuite.failedExpectations.length; j++) {
243 | var errorBarMessage = 'AfterAll ' + failedSuite.failedExpectations[j].message;
244 | var errorBarClassName = 'jasmine-bar jasmine-errored';
245 | alert.appendChild(createDom('span', {className: errorBarClassName}, errorBarMessage));
246 | }
247 | }
248 |
249 | var results = find('.jasmine-results');
250 | results.appendChild(summary);
251 |
252 | summaryList(topResults, summary);
253 |
254 | function summaryList(resultsTree, domParent) {
255 | var specListNode;
256 | for (var i = 0; i < resultsTree.children.length; i++) {
257 | var resultNode = resultsTree.children[i];
258 | if (resultNode.type == 'suite') {
259 | var suiteListNode = createDom('ul', {className: 'jasmine-suite', id: 'suite-' + resultNode.result.id},
260 | createDom('li', {className: 'jasmine-suite-detail'},
261 | createDom('a', {href: specHref(resultNode.result)}, resultNode.result.description)
262 | )
263 | );
264 |
265 | summaryList(resultNode, suiteListNode);
266 | domParent.appendChild(suiteListNode);
267 | }
268 | if (resultNode.type == 'spec') {
269 | if (domParent.getAttribute('class') != 'jasmine-specs') {
270 | specListNode = createDom('ul', {className: 'jasmine-specs'});
271 | domParent.appendChild(specListNode);
272 | }
273 | var specDescription = resultNode.result.description;
274 | if(noExpectations(resultNode.result)) {
275 | specDescription = 'SPEC HAS NO EXPECTATIONS ' + specDescription;
276 | }
277 | if(resultNode.result.status === 'pending' && resultNode.result.pendingReason !== '') {
278 | specDescription = specDescription + ' PENDING WITH MESSAGE: ' + resultNode.result.pendingReason;
279 | }
280 | specListNode.appendChild(
281 | createDom('li', {
282 | className: 'jasmine-' + resultNode.result.status,
283 | id: 'spec-' + resultNode.result.id
284 | },
285 | createDom('a', {href: specHref(resultNode.result)}, specDescription)
286 | )
287 | );
288 | }
289 | }
290 | }
291 |
292 | if (failures.length) {
293 | alert.appendChild(
294 | createDom('span', {className: 'jasmine-menu jasmine-bar jasmine-spec-list'},
295 | createDom('span', {}, 'Spec List | '),
296 | createDom('a', {className: 'jasmine-failures-menu', href: '#'}, 'Failures')));
297 | alert.appendChild(
298 | createDom('span', {className: 'jasmine-menu jasmine-bar jasmine-failure-list'},
299 | createDom('a', {className: 'jasmine-spec-list-menu', href: '#'}, 'Spec List'),
300 | createDom('span', {}, ' | Failures ')));
301 |
302 | find('.jasmine-failures-menu').onclick = function() {
303 | setMenuModeTo('jasmine-failure-list');
304 | };
305 | find('.jasmine-spec-list-menu').onclick = function() {
306 | setMenuModeTo('jasmine-spec-list');
307 | };
308 |
309 | setMenuModeTo('jasmine-failure-list');
310 |
311 | var failureNode = find('.jasmine-failures');
312 | for (var i = 0; i < failures.length; i++) {
313 | failureNode.appendChild(failures[i]);
314 | }
315 | }
316 | };
317 |
318 | return this;
319 |
320 | function find(selector) {
321 | return getContainer().querySelector('.jasmine_html-reporter ' + selector);
322 | }
323 |
324 | function clearPrior() {
325 | // return the reporter
326 | var oldReporter = find('');
327 |
328 | if(oldReporter) {
329 | getContainer().removeChild(oldReporter);
330 | }
331 | }
332 |
333 | function createDom(type, attrs, childrenVarArgs) {
334 | var el = createElement(type);
335 |
336 | for (var i = 2; i < arguments.length; i++) {
337 | var child = arguments[i];
338 |
339 | if (typeof child === 'string') {
340 | el.appendChild(createTextNode(child));
341 | } else {
342 | if (child) {
343 | el.appendChild(child);
344 | }
345 | }
346 | }
347 |
348 | for (var attr in attrs) {
349 | if (attr == 'className') {
350 | el[attr] = attrs[attr];
351 | } else {
352 | el.setAttribute(attr, attrs[attr]);
353 | }
354 | }
355 |
356 | return el;
357 | }
358 |
359 | function pluralize(singular, count) {
360 | var word = (count == 1 ? singular : singular + 's');
361 |
362 | return '' + count + ' ' + word;
363 | }
364 |
365 | function specHref(result) {
366 | return addToExistingQueryString('spec', result.fullName);
367 | }
368 |
369 | function seedHref(seed) {
370 | return addToExistingQueryString('seed', seed);
371 | }
372 |
373 | function defaultQueryString(key, value) {
374 | return '?' + key + '=' + value;
375 | }
376 |
377 | function setMenuModeTo(mode) {
378 | htmlReporterMain.setAttribute('class', 'jasmine_html-reporter ' + mode);
379 | }
380 |
381 | function noExpectations(result) {
382 | return (result.failedExpectations.length + result.passedExpectations.length) === 0 &&
383 | result.status === 'passed';
384 | }
385 | }
386 |
387 | return HtmlReporter;
388 | };
389 |
390 | jasmineRequire.HtmlSpecFilter = function() {
391 | function HtmlSpecFilter(options) {
392 | var filterString = options && options.filterString() && options.filterString().replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
393 | var filterPattern = new RegExp(filterString);
394 |
395 | this.matches = function(specName) {
396 | return filterPattern.test(specName);
397 | };
398 | }
399 |
400 | return HtmlSpecFilter;
401 | };
402 |
403 | jasmineRequire.ResultsNode = function() {
404 | function ResultsNode(result, type, parent) {
405 | this.result = result;
406 | this.type = type;
407 | this.parent = parent;
408 |
409 | this.children = [];
410 |
411 | this.addChild = function(result, type) {
412 | this.children.push(new ResultsNode(result, type, this));
413 | };
414 |
415 | this.last = function() {
416 | return this.children[this.children.length - 1];
417 | };
418 | }
419 |
420 | return ResultsNode;
421 | };
422 |
423 | jasmineRequire.QueryString = function() {
424 | function QueryString(options) {
425 |
426 | this.navigateWithNewParam = function(key, value) {
427 | options.getWindowLocation().search = this.fullStringWithNewParam(key, value);
428 | };
429 |
430 | this.fullStringWithNewParam = function(key, value) {
431 | var paramMap = queryStringToParamMap();
432 | paramMap[key] = value;
433 | return toQueryString(paramMap);
434 | };
435 |
436 | this.getParam = function(key) {
437 | return queryStringToParamMap()[key];
438 | };
439 |
440 | return this;
441 |
442 | function toQueryString(paramMap) {
443 | var qStrPairs = [];
444 | for (var prop in paramMap) {
445 | qStrPairs.push(encodeURIComponent(prop) + '=' + encodeURIComponent(paramMap[prop]));
446 | }
447 | return '?' + qStrPairs.join('&');
448 | }
449 |
450 | function queryStringToParamMap() {
451 | var paramStr = options.getWindowLocation().search.substring(1),
452 | params = [],
453 | paramMap = {};
454 |
455 | if (paramStr.length > 0) {
456 | params = paramStr.split('&');
457 | for (var i = 0; i < params.length; i++) {
458 | var p = params[i].split('=');
459 | var value = decodeURIComponent(p[1]);
460 | if (value === 'true' || value === 'false') {
461 | value = JSON.parse(value);
462 | }
463 | paramMap[decodeURIComponent(p[0])] = value;
464 | }
465 | }
466 |
467 | return paramMap;
468 | }
469 |
470 | }
471 |
472 | return QueryString;
473 | };
474 |
--------------------------------------------------------------------------------
/Module5/lib/jasmine-2.4.1/jasmine.css:
--------------------------------------------------------------------------------
1 | body { overflow-y: scroll; }
2 |
3 | .jasmine_html-reporter { background-color: #eee; padding: 5px; margin: -8px; font-size: 11px; font-family: Monaco, "Lucida Console", monospace; line-height: 14px; color: #333; }
4 | .jasmine_html-reporter a { text-decoration: none; }
5 | .jasmine_html-reporter a:hover { text-decoration: underline; }
6 | .jasmine_html-reporter p, .jasmine_html-reporter h1, .jasmine_html-reporter h2, .jasmine_html-reporter h3, .jasmine_html-reporter h4, .jasmine_html-reporter h5, .jasmine_html-reporter h6 { margin: 0; line-height: 14px; }
7 | .jasmine_html-reporter .jasmine-banner, .jasmine_html-reporter .jasmine-symbol-summary, .jasmine_html-reporter .jasmine-summary, .jasmine_html-reporter .jasmine-result-message, .jasmine_html-reporter .jasmine-spec .jasmine-description, .jasmine_html-reporter .jasmine-spec-detail .jasmine-description, .jasmine_html-reporter .jasmine-alert .jasmine-bar, .jasmine_html-reporter .jasmine-stack-trace { padding-left: 9px; padding-right: 9px; }
8 | .jasmine_html-reporter .jasmine-banner { position: relative; }
9 | .jasmine_html-reporter .jasmine-banner .jasmine-title { background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFoAAAAZCAMAAACGusnyAAACdlBMVEX/////AP+AgICqVaqAQICZM5mAVYCSSZKAQICOOY6ATYCLRouAQICJO4mSSYCIRIiPQICHPIeOR4CGQ4aMQICGPYaLRoCFQ4WKQICPPYWJRYCOQoSJQICNPoSIRICMQoSHQICHRICKQoOHQICKPoOJO4OJQYOMQICMQ4CIQYKLQICIPoKLQ4CKQICNPoKJQISMQ4KJQoSLQYKJQISLQ4KIQoSKQYKIQICIQISMQoSKQYKLQIOLQoOJQYGLQIOKQIOMQoGKQYOLQYGKQIOLQoGJQYOJQIOKQYGJQIOKQoGKQIGLQIKLQ4KKQoGLQYKJQIGKQYKJQIGKQIKJQoGKQYKLQIGKQYKLQIOJQoKKQoOJQYKKQIOJQoKKQoOKQIOLQoKKQYOLQYKJQIOKQoKKQYKKQoKJQYOKQYKLQIOKQoKLQYOKQYKLQIOJQoGKQYKJQYGJQoGKQYKLQoGLQYGKQoGJQYKKQYGJQIKKQoGJQYKLQIKKQYGLQYKKQYGKQYGKQYKJQYOKQoKJQYOKQYKLQYOLQYOKQYKLQYOKQoKKQYKKQYOKQYOJQYKKQYKLQYKKQIKKQoKKQYKKQYKKQoKJQIKKQYKLQYKKQYKKQIKKQYKKQYKKQYKKQIKKQYKJQYGLQYGKQYKKQYKKQYGKQIKKQYGKQYOJQoKKQYOLQYKKQYOKQoKKQYKKQoKKQYKKQYKJQYKLQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKJQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKLQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKmIDpEAAAA0XRSTlMAAQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyAiIyQlJycoKissLS4wMTQ1Njc4OTo7PDw+P0BCQ0RISUpLTE1OUFNUVVdYWFlaW15fYGFiY2ZnaGlqa2xtb3BxcnN0dnh5ent8fX5/gIGChIWIioyNjo+QkZOUlZaYmZqbnJ2eoKGio6WmqKmsra6vsLGztre4ubq7vL2+wMHDxMjJysvNzs/Q0dLU1tfY2dvc3t/g4eLj5ebn6Onq6+zt7u/w8vP09fb3+Pn6+/z9/vkVQXAAAAMaSURBVHhe5dXxV1N1GMfxz2ABbDgIAm5VDJOyVDIJLUMaVpBWUZUaGbmqoGpZRSiGiRWp6KoZ5AB0ZY50RImZQIlahKkMYXv/R90dBvET/rJfOr3Ouc8v99zPec59zvf56j+vYKlViSf7250X4Mr3O29Tgq08BdGB4DhcekEJ5YkQKFsgWZdtj9JpV+I8xPjLFqkrsEIqO8PHSpis36jWazcqjEsfJjkvRssVU37SdIOu4XCf5vEJPsnwJpnRNU9JmxhMk8l1gehIrq7hTFjzOD+Vf88629qKMJVNltInFeRexRQyJlNeqd1iGDlSzrIUIyXbyFfm3RYprcQRe7lqtWyGYbfc6dT0R2vmdOOkX3u55C1rP37ftiH+tDby4r/RBT0w8TyEkr+epB9XgPDmSYYWbrhCuFYaIyw3fDQAXTnSkh+ANofiHmWf9l+FY1I90FdQTetstO00o23novzVsJ7uB3/C5TkbjRwZ5JerwV4iRWq9HFbFMaK/d0TYqayRiQPuIxxS3Bu8JWU90/60tKi7vkhaznez0a/TbVOKj5CaOZh6fWG6/Lyv9B/ZLR1gw/S/fpbeVD3MCW1li6SvWDOn65tr99/uvWtBS0XDm4s1t+sOHpG0kpBKx/l77wOSnxLpcx6TXmXLTPQOKYOf9Q1dfr8/SJ2mFdCvl1Yl93DiHUZvXeLJbGSzYu5gVJ2slbSakOR8dxCq5adQ2oFLqsE9Ex3L4qQO0eOPeU5x56bypXp4onSEb5OkICX6lDat55TeoztNKQcJaakrz9KCb95oD69IKq+yKW4XPjknaS52V0TZqE2cTtXjcHSCRmUO88e+85hj3EP74i9p8pylw7lxgMDyyl6OV7ZejnjNMfatu87LxRbH0IS35gt2a4ZjmGpVBdKK3Wr6INk8jWWSGqbA55CKgjBRC6E9w78ydTg3ABS3AFV1QN0Y4Aa2pgEjWnQURj9L0ayK6R2ysEqxHUKzYnLvvyU+i9KM2JHJzE4vyZOyDcOwOsySajeLPc8sNvPJkFlyJd20wpqAzZeAfZ3oWybxd+P/3j+SG3uSBdf2VQAAAABJRU5ErkJggg==') no-repeat; background: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhLS0gQ3JlYXRlZCB3aXRoIElua3NjYXBlIChodHRwOi8vd3d3Lmlua3NjYXBlLm9yZy8pIC0tPgoKPHN2ZwogICB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iCiAgIHhtbG5zOmNjPSJodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9ucyMiCiAgIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyIKICAgeG1sbnM6c3ZnPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICAgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIgogICB4bWxuczppbmtzY2FwZT0iaHR0cDovL3d3dy5pbmtzY2FwZS5vcmcvbmFtZXNwYWNlcy9pbmtzY2FwZSIKICAgdmVyc2lvbj0iMS4xIgogICB3aWR0aD0iNjgxLjk2MjUyIgogICBoZWlnaHQ9IjE4Ny41IgogICBpZD0ic3ZnMiIKICAgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+PG1ldGFkYXRhCiAgICAgaWQ9Im1ldGFkYXRhOCI+PHJkZjpSREY+PGNjOldvcmsKICAgICAgICAgcmRmOmFib3V0PSIiPjxkYzpmb3JtYXQ+aW1hZ2Uvc3ZnK3htbDwvZGM6Zm9ybWF0PjxkYzp0eXBlCiAgICAgICAgICAgcmRmOnJlc291cmNlPSJodHRwOi8vcHVybC5vcmcvZGMvZGNtaXR5cGUvU3RpbGxJbWFnZSIgLz48L2NjOldvcms+PC9yZGY6UkRGPjwvbWV0YWRhdGE+PGRlZnMKICAgICBpZD0iZGVmczYiPjxjbGlwUGF0aAogICAgICAgaWQ9ImNsaXBQYXRoMTgiPjxwYXRoCiAgICAgICAgIGQ9Ik0gMCwxNTAwIDAsMCBsIDU0NTUuNzQsMCAwLDE1MDAgTCAwLDE1MDAgeiIKICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgaWQ9InBhdGgyMCIgLz48L2NsaXBQYXRoPjwvZGVmcz48ZwogICAgIHRyYW5zZm9ybT0ibWF0cml4KDEuMjUsMCwwLC0xLjI1LDAsMTg3LjUpIgogICAgIGlkPSJnMTAiPjxnCiAgICAgICB0cmFuc2Zvcm09InNjYWxlKDAuMSwwLjEpIgogICAgICAgaWQ9ImcxMiI+PGcKICAgICAgICAgaWQ9ImcxNCI+PGcKICAgICAgICAgICBjbGlwLXBhdGg9InVybCgjY2xpcFBhdGgxOCkiCiAgICAgICAgICAgaWQ9ImcxNiI+PHBhdGgKICAgICAgICAgICAgIGQ9Im0gMTU0NCw1OTkuNDM0IGMgMC45MiwtNDAuMzUyIDI1LjY4LC04MS42MDIgNzEuNTMsLTgxLjYwMiAyNy41MSwwIDQ3LjY4LDEyLjgzMiA2MS40NCwzNS43NTQgMTIuODMsMjIuOTMgMTIuODMsNTYuODUyIDEyLjgzLDgyLjUyNyBsIDAsMzI5LjE4NCAtNzEuNTIsMCAwLDEwNC41NDMgMjY2LjgzLDAgMCwtMTA0LjU0MyAtNzAuNiwwIDAsLTM0NC43NyBjIDAsLTU4LjY5MSAtMy42OCwtMTA0LjUzMSAtNDQuOTMsLTE1Mi4yMTggLTM2LjY4LC00Mi4xOCAtOTYuMjgsLTY2LjAyIC0xNTMuMTQsLTY2LjAyIC0xMTcuMzcsMCAtMjA3LjI0LDc3Ljk0MSAtMjAyLjY0LDE5Ny4xNDUgbCAxMzAuMiwwIgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoMjIiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDIzMDEuNCw2NjIuNjk1IGMgMCw4MC43MDMgLTY2Ljk0LDE0NS44MTMgLTE0Ny42MywxNDUuODEzIC04My40NCwwIC0xNDcuNjMsLTY4Ljc4MSAtMTQ3LjYzLC0xNTEuMzAxIDAsLTc5Ljc4NSA2Ni45NCwtMTQ1LjgwMSAxNDUuOCwtMTQ1LjgwMSA4NC4zNSwwIDE0OS40Niw2Ny44NTIgMTQ5LjQ2LDE1MS4yODkgeiBtIC0xLjgzLC0xODEuNTQ3IGMgLTM1Ljc3LC01NC4wOTcgLTkzLjUzLC03OC44NTkgLTE1Ny43MiwtNzguODU5IC0xNDAuMywwIC0yNTEuMjQsMTE2LjQ0OSAtMjUxLjI0LDI1NC45MTggMCwxNDIuMTI5IDExMy43LDI2MC40MSAyNTYuNzQsMjYwLjQxIDYzLjI3LDAgMTE4LjI5LC0yOS4zMzYgMTUyLjIyLC04Mi41MjMgbCAwLDY5LjY4NyAxNzUuMTQsMCAwLC0xMDQuNTI3IC02MS40NCwwIDAsLTI4MC41OTggNjEuNDQsMCAwLC0xMDQuNTI3IC0xNzUuMTQsMCAwLDY2LjAxOSIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDI0IgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSAyNjIyLjMzLDU1Ny4yNTggYyAzLjY3LC00NC4wMTYgMzMuMDEsLTczLjM0OCA3OC44NiwtNzMuMzQ4IDMzLjkzLDAgNjYuOTMsMjMuODI0IDY2LjkzLDYwLjUwNCAwLDQ4LjYwNiAtNDUuODQsNTYuODU2IC04My40NCw2Ni45NDEgLTg1LjI4LDIyLjAwNCAtMTc4LjgxLDQ4LjYwNiAtMTc4LjgxLDE1NS44NzkgMCw5My41MzYgNzguODYsMTQ3LjYzMyAxNjUuOTgsMTQ3LjYzMyA0NCwwIDgzLjQzLC05LjE3NiAxMTAuOTQsLTQ0LjAwOCBsIDAsMzMuOTIyIDgyLjUzLDAgMCwtMTMyLjk2NSAtMTA4LjIxLDAgYyAtMS44MywzNC44NTYgLTI4LjQyLDU3Ljc3NCAtNjMuMjYsNTcuNzc0IC0zMC4yNiwwIC02Mi4zNSwtMTcuNDIyIC02Mi4zNSwtNTEuMzQ4IDAsLTQ1Ljg0NyA0NC45MywtNTUuOTMgODAuNjksLTY0LjE4IDg4LjAyLC0yMC4xNzUgMTgyLjQ3LC00Ny42OTUgMTgyLjQ3LC0xNTcuNzM0IDAsLTk5LjAyNyAtODMuNDQsLTE1NC4wMzkgLTE3NS4xMywtMTU0LjAzOSAtNDkuNTMsMCAtOTQuNDYsMTUuNTgyIC0xMjYuNTUsNTMuMTggbCAwLC00MC4zNCAtODUuMjcsMCAwLDE0Mi4xMjkgMTE0LjYyLDAiCiAgICAgICAgICAgICBpbmtzY2FwZTpjb25uZWN0b3ItY3VydmF0dXJlPSIwIgogICAgICAgICAgICAgaWQ9InBhdGgyNiIKICAgICAgICAgICAgIHN0eWxlPSJmaWxsOiM4YTQxODI7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiIC8+PHBhdGgKICAgICAgICAgICAgIGQ9Im0gMjk4OC4xOCw4MDAuMjU0IC02My4yNiwwIDAsMTA0LjUyNyAxNjUuMDUsMCAwLC03My4zNTUgYyAzMS4xOCw1MS4zNDcgNzguODYsODUuMjc3IDE0MS4yMSw4NS4yNzcgNjcuODUsMCAxMjQuNzEsLTQxLjI1OCAxNTIuMjEsLTEwMi42OTkgMjYuNiw2Mi4zNTEgOTIuNjIsMTAyLjY5OSAxNjAuNDcsMTAyLjY5OSA1My4xOSwwIDEwNS40NiwtMjIgMTQxLjIxLC02Mi4zNTEgMzguNTIsLTQ0LjkzOCAzOC41MiwtOTMuNTMyIDM4LjUyLC0xNDkuNDU3IGwgMCwtMTg1LjIzOSA2My4yNywwIDAsLTEwNC41MjcgLTIzOC40MiwwIDAsMTA0LjUyNyA2My4yOCwwIDAsMTU3LjcxNSBjIDAsMzIuMTAyIDAsNjAuNTI3IC0xNC42Nyw4OC45NTcgLTE4LjM0LDI2LjU4MiAtNDguNjEsNDAuMzQ0IC03OS43Nyw0MC4zNDQgLTMwLjI2LDAgLTYzLjI4LC0xMi44NDQgLTgyLjUzLC0zNi42NzIgLTIyLjkzLC0yOS4zNTUgLTIyLjkzLC01Ni44NjMgLTIyLjkzLC05Mi42MjkgbCAwLC0xNTcuNzE1IDYzLjI3LDAgMCwtMTA0LjUyNyAtMjM4LjQxLDAgMCwxMDQuNTI3IDYzLjI4LDAgMCwxNTAuMzgzIGMgMCwyOS4zNDggMCw2Ni4wMjMgLTE0LjY3LDkxLjY5OSAtMTUuNTksMjkuMzM2IC00Ny42OSw0NC45MzQgLTgwLjcsNDQuOTM0IC0zMS4xOCwwIC01Ny43NywtMTEuMDA4IC03Ny45NCwtMzUuNzc0IC0yNC43NywtMzAuMjUzIC0yNi42LC02Mi4zNDMgLTI2LjYsLTk5Ljk0MSBsIDAsLTE1MS4zMDEgNjMuMjcsMCAwLC0xMDQuNTI3IC0yMzguNCwwIDAsMTA0LjUyNyA2My4yNiwwIDAsMjgwLjU5OCIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDI4IgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSAzOTk4LjY2LDk1MS41NDcgLTExMS44NywwIDAsMTE4LjI5MyAxMTEuODcsMCAwLC0xMTguMjkzIHogbSAwLC00MzEuODkxIDYzLjI3LDAgMCwtMTA0LjUyNyAtMjM5LjMzLDAgMCwxMDQuNTI3IDY0LjE5LDAgMCwyODAuNTk4IC02My4yNywwIDAsMTA0LjUyNyAxNzUuMTQsMCAwLC0zODUuMTI1IgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoMzAiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDQxNTkuMTIsODAwLjI1NCAtNjMuMjcsMCAwLDEwNC41MjcgMTc1LjE0LDAgMCwtNjkuNjg3IGMgMjkuMzUsNTQuMTAxIDg0LjM2LDgwLjY5OSAxNDQuODcsODAuNjk5IDUzLjE5LDAgMTA1LjQ1LC0yMi4wMTYgMTQxLjIyLC02MC41MjcgNDAuMzQsLTQ0LjkzNCA0MS4yNiwtODguMDMyIDQxLjI2LC0xNDMuOTU3IGwgMCwtMTkxLjY1MyA2My4yNywwIDAsLTEwNC41MjcgLTIzOC40LDAgMCwxMDQuNTI3IDYzLjI2LDAgMCwxNTguNjM3IGMgMCwzMC4yNjIgMCw2MS40MzQgLTE5LjI2LDg4LjAzNSAtMjAuMTcsMjYuNTgyIC01My4xOCwzOS40MTQgLTg2LjE5LDM5LjQxNCAtMzMuOTMsMCAtNjguNzcsLTEzLjc1IC04OC45NCwtNDEuMjUgLTIxLjA5LC0yNy41IC0yMS4wOSwtNjkuNjg3IC0yMS4wOSwtMTAyLjcwNyBsIDAsLTE0Mi4xMjkgNjMuMjYsMCAwLC0xMDQuNTI3IC0yMzguNCwwIDAsMTA0LjUyNyA2My4yNywwIDAsMjgwLjU5OCIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDMyIgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSA1MDgyLjQ4LDcwMy45NjUgYyAtMTkuMjQsNzAuNjA1IC04MS42LDExNS41NDcgLTE1NC4wNCwxMTUuNTQ3IC02Ni4wNCwwIC0xMjkuMywtNTEuMzQ4IC0xNDMuMDUsLTExNS41NDcgbCAyOTcuMDksMCB6IG0gODUuMjcsLTE0NC44ODMgYyAtMzguNTEsLTkzLjUyMyAtMTI5LjI3LC0xNTYuNzkzIC0yMzEuMDUsLTE1Ni43OTMgLTE0My4wNywwIC0yNTcuNjgsMTExLjg3MSAtMjU3LjY4LDI1NS44MzYgMCwxNDQuODgzIDEwOS4xMiwyNjEuMzI4IDI1NC45MSwyNjEuMzI4IDY3Ljg3LDAgMTM1LjcyLC0zMC4yNTggMTgzLjM5LC03OC44NjMgNDguNjIsLTUxLjM0NCA2OC43OSwtMTEzLjY5NSA2OC43OSwtMTgzLjM4MyBsIC0zLjY3LC0zOS40MzQgLTM5Ni4xMywwIGMgMTQuNjcsLTY3Ljg2MyA3Ny4wMywtMTE3LjM2MyAxNDYuNzIsLTExNy4zNjMgNDguNTksMCA5MC43NiwxOC4zMjggMTE4LjI4LDU4LjY3MiBsIDExNi40NCwwIgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoMzQiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDY5MC44OTUsODUwLjcwMyA5MC43NSwwIDIyLjU0MywzMS4wMzUgMCwyNDMuMTIyIC0xMzUuODI5LDAgMCwtMjQzLjE0MSAyMi41MzYsLTMxLjAxNiIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDM2IgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSA2MzIuMzk1LDc0Mi4yNTggMjguMDM5LDg2LjMwNCAtMjIuNTUxLDMxLjA0IC0yMzEuMjIzLDc1LjEyOCAtNDEuOTc2LC0xMjkuMTgzIDIzMS4yNTcsLTc1LjEzNyAzNi40NTQsMTEuODQ4IgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoMzgiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDcxNy40NDksNjUzLjEwNSAtNzMuNDEsNTMuMzYgLTM2LjQ4OCwtMTEuODc1IC0xNDIuOTAzLC0xOTYuNjkyIDEwOS44ODMsLTc5LjgyOCAxNDIuOTE4LDE5Ni43MDMgMCwzOC4zMzIiCiAgICAgICAgICAgICBpbmtzY2FwZTpjb25uZWN0b3ItY3VydmF0dXJlPSIwIgogICAgICAgICAgICAgaWQ9InBhdGg0MCIKICAgICAgICAgICAgIHN0eWxlPSJmaWxsOiM4YTQxODI7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiIC8+PHBhdGgKICAgICAgICAgICAgIGQ9Im0gODI4LjUyLDcwNi40NjUgLTczLjQyNiwtNTMuMzQgMC4wMTEsLTM4LjM1OSBMIDg5OC4wMDQsNDE4LjA3IDEwMDcuOSw0OTcuODk4IDg2NC45NzMsNjk0LjYwOSA4MjguNTIsNzA2LjQ2NSIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDQyIgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSA4MTIuMDg2LDgyOC41ODYgMjguMDU1LC04Ni4zMiAzNi40ODQsLTExLjgzNiAyMzEuMjI1LDc1LjExNyAtNDEuOTcsMTI5LjE4MyAtMjMxLjIzOSwtNzUuMTQgLTIyLjU1NSwtMzEuMDA0IgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoNDQiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDczNi4zMDEsMTMzNS44OCBjIC0zMjMuMDQ3LDAgLTU4NS44NzUsLTI2Mi43OCAtNTg1Ljg3NSwtNTg1Ljc4MiAwLC0zMjMuMTE4IDI2Mi44MjgsLTU4NS45NzcgNTg1Ljg3NSwtNTg1Ljk3NyAzMjMuMDE5LDAgNTg1LjgwOSwyNjIuODU5IDU4NS44MDksNTg1Ljk3NyAwLDMyMy4wMDIgLTI2Mi43OSw1ODUuNzgyIC01ODUuODA5LDU4NS43ODIgbCAwLDAgeiBtIDAsLTExOC42MSBjIDI1Ny45NzIsMCA0NjcuMTg5LC0yMDkuMTMgNDY3LjE4OSwtNDY3LjE3MiAwLC0yNTguMTI5IC0yMDkuMjE3LC00NjcuMzQ4IC00NjcuMTg5LC00NjcuMzQ4IC0yNTguMDc0LDAgLTQ2Ny4yNTQsMjA5LjIxOSAtNDY3LjI1NCw0NjcuMzQ4IDAsMjU4LjA0MiAyMDkuMTgsNDY3LjE3MiA0NjcuMjU0LDQ2Ny4xNzIiCiAgICAgICAgICAgICBpbmtzY2FwZTpjb25uZWN0b3ItY3VydmF0dXJlPSIwIgogICAgICAgICAgICAgaWQ9InBhdGg0NiIKICAgICAgICAgICAgIHN0eWxlPSJmaWxsOiM4YTQxODI7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiIC8+PHBhdGgKICAgICAgICAgICAgIGQ9Im0gMTA5MS4xMyw2MTkuODgzIC0xNzUuNzcxLDU3LjEyMSAxMS42MjksMzUuODA4IDE3NS43NjIsLTU3LjEyMSAtMTEuNjIsLTM1LjgwOCIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDQ4IgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0iTSA4NjYuOTU3LDkwMi4wNzQgODM2LjUsOTI0LjE5OSA5NDUuMTIxLDEwNzMuNzMgOTc1LjU4NiwxMDUxLjYxIDg2Ni45NTcsOTAyLjA3NCIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDUwIgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0iTSA2MDcuNDY1LDkwMy40NDUgNDk4Ljg1NSwxMDUyLjk3IDUyOS4zMiwxMDc1LjEgNjM3LjkzLDkyNS41NjYgNjA3LjQ2NSw5MDMuNDQ1IgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoNTIiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDM4MC42ODgsNjIyLjEyOSAtMTEuNjI2LDM1LjgwMSAxNzUuNzU4LDU3LjA5IDExLjYyMSwtMzUuODAxIC0xNzUuNzUzLC01Ny4wOSIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDU0IgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSA3MTYuMjg5LDM3Ni41OSAzNy42NDA2LDAgMCwxODQuODE2IC0zNy42NDA2LDAgMCwtMTg0LjgxNiB6IgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoNTYiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjwvZz48L2c+PC9nPjwvZz48L3N2Zz4=') no-repeat, none; -moz-background-size: 100%; -o-background-size: 100%; -webkit-background-size: 100%; background-size: 100%; display: block; float: left; width: 90px; height: 25px; }
10 | .jasmine_html-reporter .jasmine-banner .jasmine-version { margin-left: 14px; position: relative; top: 6px; }
11 | .jasmine_html-reporter #jasmine_content { position: fixed; right: 100%; }
12 | .jasmine_html-reporter .jasmine-version { color: #aaa; }
13 | .jasmine_html-reporter .jasmine-banner { margin-top: 14px; }
14 | .jasmine_html-reporter .jasmine-duration { color: #fff; float: right; line-height: 28px; padding-right: 9px; }
15 | .jasmine_html-reporter .jasmine-symbol-summary { overflow: hidden; *zoom: 1; margin: 14px 0; }
16 | .jasmine_html-reporter .jasmine-symbol-summary li { display: inline-block; height: 10px; width: 14px; font-size: 16px; }
17 | .jasmine_html-reporter .jasmine-symbol-summary li.jasmine-passed { font-size: 14px; }
18 | .jasmine_html-reporter .jasmine-symbol-summary li.jasmine-passed:before { color: #007069; content: "\02022"; }
19 | .jasmine_html-reporter .jasmine-symbol-summary li.jasmine-failed { line-height: 9px; }
20 | .jasmine_html-reporter .jasmine-symbol-summary li.jasmine-failed:before { color: #ca3a11; content: "\d7"; font-weight: bold; margin-left: -1px; }
21 | .jasmine_html-reporter .jasmine-symbol-summary li.jasmine-disabled { font-size: 14px; }
22 | .jasmine_html-reporter .jasmine-symbol-summary li.jasmine-disabled:before { color: #bababa; content: "\02022"; }
23 | .jasmine_html-reporter .jasmine-symbol-summary li.jasmine-pending { line-height: 17px; }
24 | .jasmine_html-reporter .jasmine-symbol-summary li.jasmine-pending:before { color: #ba9d37; content: "*"; }
25 | .jasmine_html-reporter .jasmine-symbol-summary li.jasmine-empty { font-size: 14px; }
26 | .jasmine_html-reporter .jasmine-symbol-summary li.jasmine-empty:before { color: #ba9d37; content: "\02022"; }
27 | .jasmine_html-reporter .jasmine-run-options { float: right; margin-right: 5px; border: 1px solid #8a4182; color: #8a4182; position: relative; line-height: 20px; }
28 | .jasmine_html-reporter .jasmine-run-options .jasmine-trigger { cursor: pointer; padding: 8px 16px; }
29 | .jasmine_html-reporter .jasmine-run-options .jasmine-payload { position: absolute; display: none; right: -1px; border: 1px solid #8a4182; background-color: #eee; white-space: nowrap; padding: 4px 8px; }
30 | .jasmine_html-reporter .jasmine-run-options .jasmine-payload.jasmine-open { display: block; }
31 | .jasmine_html-reporter .jasmine-bar { line-height: 28px; font-size: 14px; display: block; color: #eee; }
32 | .jasmine_html-reporter .jasmine-bar.jasmine-failed { background-color: #ca3a11; }
33 | .jasmine_html-reporter .jasmine-bar.jasmine-passed { background-color: #007069; }
34 | .jasmine_html-reporter .jasmine-bar.jasmine-skipped { background-color: #bababa; }
35 | .jasmine_html-reporter .jasmine-bar.jasmine-errored { background-color: #ca3a11; }
36 | .jasmine_html-reporter .jasmine-bar.jasmine-menu { background-color: #fff; color: #aaa; }
37 | .jasmine_html-reporter .jasmine-bar.jasmine-menu a { color: #333; }
38 | .jasmine_html-reporter .jasmine-bar a { color: white; }
39 | .jasmine_html-reporter.jasmine-spec-list .jasmine-bar.jasmine-menu.jasmine-failure-list, .jasmine_html-reporter.jasmine-spec-list .jasmine-results .jasmine-failures { display: none; }
40 | .jasmine_html-reporter.jasmine-failure-list .jasmine-bar.jasmine-menu.jasmine-spec-list, .jasmine_html-reporter.jasmine-failure-list .jasmine-summary { display: none; }
41 | .jasmine_html-reporter .jasmine-results { margin-top: 14px; }
42 | .jasmine_html-reporter .jasmine-summary { margin-top: 14px; }
43 | .jasmine_html-reporter .jasmine-summary ul { list-style-type: none; margin-left: 14px; padding-top: 0; padding-left: 0; }
44 | .jasmine_html-reporter .jasmine-summary ul.jasmine-suite { margin-top: 7px; margin-bottom: 7px; }
45 | .jasmine_html-reporter .jasmine-summary li.jasmine-passed a { color: #007069; }
46 | .jasmine_html-reporter .jasmine-summary li.jasmine-failed a { color: #ca3a11; }
47 | .jasmine_html-reporter .jasmine-summary li.jasmine-empty a { color: #ba9d37; }
48 | .jasmine_html-reporter .jasmine-summary li.jasmine-pending a { color: #ba9d37; }
49 | .jasmine_html-reporter .jasmine-summary li.jasmine-disabled a { color: #bababa; }
50 | .jasmine_html-reporter .jasmine-description + .jasmine-suite { margin-top: 0; }
51 | .jasmine_html-reporter .jasmine-suite { margin-top: 14px; }
52 | .jasmine_html-reporter .jasmine-suite a { color: #333; }
53 | .jasmine_html-reporter .jasmine-failures .jasmine-spec-detail { margin-bottom: 28px; }
54 | .jasmine_html-reporter .jasmine-failures .jasmine-spec-detail .jasmine-description { background-color: #ca3a11; }
55 | .jasmine_html-reporter .jasmine-failures .jasmine-spec-detail .jasmine-description a { color: white; }
56 | .jasmine_html-reporter .jasmine-result-message { padding-top: 14px; color: #333; white-space: pre; }
57 | .jasmine_html-reporter .jasmine-result-message span.jasmine-result { display: block; }
58 | .jasmine_html-reporter .jasmine-stack-trace { margin: 5px 0 0 0; max-height: 224px; overflow: auto; line-height: 18px; color: #666; border: 1px solid #ddd; background: white; white-space: pre; }
59 |
--------------------------------------------------------------------------------
/Module5/lib/angular-ui-router.min.js:
--------------------------------------------------------------------------------
1 | /**
2 | * State-based routing for AngularJS
3 | * @version v0.3.1
4 | * @link http://angular-ui.github.com/
5 | * @license MIT License, http://www.opensource.org/licenses/MIT
6 | */
7 | "undefined"!=typeof module&&"undefined"!=typeof exports&&module.exports===exports&&(module.exports="ui.router"),function(a,b,c){"use strict";function d(a,b){return R(new(R(function(){},{prototype:a})),b)}function e(a){return Q(arguments,function(b){b!==a&&Q(b,function(b,c){a.hasOwnProperty(c)||(a[c]=b)})}),a}function f(a,b){var c=[];for(var d in a.path){if(a.path[d]!==b.path[d])break;c.push(a.path[d])}return c}function g(a){if(Object.keys)return Object.keys(a);var b=[];return Q(a,function(a,c){b.push(c)}),b}function h(a,b){if(Array.prototype.indexOf)return a.indexOf(b,Number(arguments[2])||0);var c=a.length>>>0,d=Number(arguments[2])||0;for(d=0>d?Math.ceil(d):Math.floor(d),0>d&&(d+=c);c>d;d++)if(d in a&&a[d]===b)return d;return-1}function i(a,b,c,d){var e,i=f(c,d),j={},k=[];for(var l in i)if(i[l]&&i[l].params&&(e=g(i[l].params),e.length))for(var m in e)h(k,e[m])>=0||(k.push(e[m]),j[e[m]]=a[e[m]]);return R({},j,b)}function j(a,b,c){if(!c){c=[];for(var d in a)c.push(d)}for(var e=0;e "));if(s[c]=d,N(a))q.push(c,[function(){return b.get(a)}],j);else{var e=b.annotate(a);Q(e,function(a){a!==c&&i.hasOwnProperty(a)&&n(i[a],a)}),q.push(c,a,e)}r.pop(),s[c]=f}}function o(a){return O(a)&&a.then&&a.$$promises}if(!O(i))throw new Error("'invocables' must be an object");var p=g(i||{}),q=[],r=[],s={};return Q(i,n),i=r=s=null,function(d,f,g){function h(){--u||(v||e(t,f.$$values),r.$$values=t,r.$$promises=r.$$promises||!0,delete r.$$inheritedValues,n.resolve(t))}function i(a){r.$$failure=a,n.reject(a)}function j(c,e,f){function j(a){l.reject(a),i(a)}function k(){if(!L(r.$$failure))try{l.resolve(b.invoke(e,g,t)),l.promise.then(function(a){t[c]=a,h()},j)}catch(a){j(a)}}var l=a.defer(),m=0;Q(f,function(a){s.hasOwnProperty(a)&&!d.hasOwnProperty(a)&&(m++,s[a].then(function(b){t[a]=b,--m||k()},j))}),m||k(),s[c]=l.promise}if(o(d)&&g===c&&(g=f,f=d,d=null),d){if(!O(d))throw new Error("'locals' must be an object")}else d=k;if(f){if(!o(f))throw new Error("'parent' must be a promise returned by $resolve.resolve()")}else f=l;var n=a.defer(),r=n.promise,s=r.$$promises={},t=R({},d),u=1+q.length/3,v=!1;if(L(f.$$failure))return i(f.$$failure),r;f.$$inheritedValues&&e(t,m(f.$$inheritedValues,p)),R(s,f.$$promises),f.$$values?(v=e(t,m(f.$$values,p)),r.$$inheritedValues=m(f.$$values,p),h()):(f.$$inheritedValues&&(r.$$inheritedValues=m(f.$$inheritedValues,p)),f.then(h,i));for(var w=0,x=q.length;x>w;w+=3)d.hasOwnProperty(q[w])?h():j(q[w],q[w+1],q[w+2]);return r}},this.resolve=function(a,b,c,d){return this.study(a)(b,c,d)}}function q(a,b,c){this.fromConfig=function(a,b,c){return L(a.template)?this.fromString(a.template,b):L(a.templateUrl)?this.fromUrl(a.templateUrl,b):L(a.templateProvider)?this.fromProvider(a.templateProvider,b,c):null},this.fromString=function(a,b){return M(a)?a(b):a},this.fromUrl=function(c,d){return M(c)&&(c=c(d)),null==c?null:a.get(c,{cache:b,headers:{Accept:"text/html"}}).then(function(a){return a.data})},this.fromProvider=function(a,b,d){return c.invoke(a,null,d||{params:b})}}function r(a,b,e){function f(b,c,d,e){if(q.push(b),o[b])return o[b];if(!/^\w+([-.]+\w+)*(?:\[\])?$/.test(b))throw new Error("Invalid parameter name '"+b+"' in pattern '"+a+"'");if(p[b])throw new Error("Duplicate parameter name '"+b+"' in pattern '"+a+"'");return p[b]=new U.Param(b,c,d,e),p[b]}function g(a,b,c,d){var e=["",""],f=a.replace(/[\\\[\]\^$*+?.()|{}]/g,"\\$&");if(!b)return f;switch(c){case!1:e=["(",")"+(d?"?":"")];break;case!0:f=f.replace(/\/$/,""),e=["(?:/(",")|/)?"];break;default:e=["("+c+"|",")?"]}return f+e[0]+b+e[1]}function h(e,f){var g,h,i,j,k;return g=e[2]||e[3],k=b.params[g],i=a.substring(m,e.index),h=f?e[4]:e[4]||("*"==e[1]?".*":null),h&&(j=U.type(h)||d(U.type("string"),{pattern:new RegExp(h,b.caseInsensitive?"i":c)})),{id:g,regexp:h,segment:i,type:j,cfg:k}}b=R({params:{}},O(b)?b:{});var i,j=/([:*])([\w\[\]]+)|\{([\w\[\]]+)(?:\:\s*((?:[^{}\\]+|\\.|\{(?:[^{}\\]+|\\.)*\})+))?\}/g,k=/([:]?)([\w\[\].-]+)|\{([\w\[\].-]+)(?:\:\s*((?:[^{}\\]+|\\.|\{(?:[^{}\\]+|\\.)*\})+))?\}/g,l="^",m=0,n=this.segments=[],o=e?e.params:{},p=this.params=e?e.params.$$new():new U.ParamSet,q=[];this.source=a;for(var r,s,t;(i=j.exec(a))&&(r=h(i,!1),!(r.segment.indexOf("?")>=0));)s=f(r.id,r.type,r.cfg,"path"),l+=g(r.segment,s.type.pattern.source,s.squash,s.isOptional),n.push(r.segment),m=j.lastIndex;t=a.substring(m);var u=t.indexOf("?");if(u>=0){var v=this.sourceSearch=t.substring(u);if(t=t.substring(0,u),this.sourcePath=a.substring(0,m+u),v.length>0)for(m=0;i=k.exec(v);)r=h(i,!0),s=f(r.id,r.type,r.cfg,"search"),m=j.lastIndex}else this.sourcePath=a,this.sourceSearch="";l+=g(t)+(b.strict===!1?"/?":"")+"$",n.push(t),this.regexp=new RegExp(l,b.caseInsensitive?"i":c),this.prefix=n[0],this.$$paramNames=q}function s(a){R(this,a)}function t(){function a(a){return null!=a?a.toString().replace(/~/g,"~~").replace(/\//g,"~2F"):a}function e(a){return null!=a?a.toString().replace(/~2F/g,"/").replace(/~~/g,"~"):a}function f(){return{strict:p,caseInsensitive:m}}function i(a){return M(a)||P(a)&&M(a[a.length-1])}function j(){for(;w.length;){var a=w.shift();if(a.pattern)throw new Error("You cannot override a type's .pattern at runtime.");b.extend(u[a.name],l.invoke(a.def))}}function k(a){R(this,a||{})}U=this;var l,m=!1,p=!0,q=!1,u={},v=!0,w=[],x={string:{encode:a,decode:e,is:function(a){return null==a||!L(a)||"string"==typeof a},pattern:/[^\/]*/},"int":{encode:a,decode:function(a){return parseInt(a,10)},is:function(a){return L(a)&&this.decode(a.toString())===a},pattern:/\d+/},bool:{encode:function(a){return a?1:0},decode:function(a){return 0!==parseInt(a,10)},is:function(a){return a===!0||a===!1},pattern:/0|1/},date:{encode:function(a){return this.is(a)?[a.getFullYear(),("0"+(a.getMonth()+1)).slice(-2),("0"+a.getDate()).slice(-2)].join("-"):c},decode:function(a){if(this.is(a))return a;var b=this.capture.exec(a);return b?new Date(b[1],b[2]-1,b[3]):c},is:function(a){return a instanceof Date&&!isNaN(a.valueOf())},equals:function(a,b){return this.is(a)&&this.is(b)&&a.toISOString()===b.toISOString()},pattern:/[0-9]{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[1-2][0-9]|3[0-1])/,capture:/([0-9]{4})-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])/},json:{encode:b.toJson,decode:b.fromJson,is:b.isObject,equals:b.equals,pattern:/[^\/]*/},any:{encode:b.identity,decode:b.identity,equals:b.equals,pattern:/.*/}};t.$$getDefaultValue=function(a){if(!i(a.value))return a.value;if(!l)throw new Error("Injectable functions cannot be called at configuration time");return l.invoke(a.value)},this.caseInsensitive=function(a){return L(a)&&(m=a),m},this.strictMode=function(a){return L(a)&&(p=a),p},this.defaultSquashPolicy=function(a){if(!L(a))return q;if(a!==!0&&a!==!1&&!N(a))throw new Error("Invalid squash policy: "+a+". Valid policies: false, true, arbitrary-string");return q=a,a},this.compile=function(a,b){return new r(a,R(f(),b))},this.isMatcher=function(a){if(!O(a))return!1;var b=!0;return Q(r.prototype,function(c,d){M(c)&&(b=b&&L(a[d])&&M(a[d]))}),b},this.type=function(a,b,c){if(!L(b))return u[a];if(u.hasOwnProperty(a))throw new Error("A type named '"+a+"' has already been defined.");return u[a]=new s(R({name:a},b)),c&&(w.push({name:a,def:c}),v||j()),this},Q(x,function(a,b){u[b]=new s(R({name:b},a))}),u=d(u,{}),this.$get=["$injector",function(a){return l=a,v=!1,j(),Q(x,function(a,b){u[b]||(u[b]=new s(a))}),this}],this.Param=function(a,d,e,f){function j(a){var b=O(a)?g(a):[],c=-1===h(b,"value")&&-1===h(b,"type")&&-1===h(b,"squash")&&-1===h(b,"array");return c&&(a={value:a}),a.$$fn=i(a.value)?a.value:function(){return a.value},a}function k(c,d,e){if(c.type&&d)throw new Error("Param '"+a+"' has two type configurations.");return d?d:c.type?b.isString(c.type)?u[c.type]:c.type instanceof s?c.type:new s(c.type):"config"===e?u.any:u.string}function m(){var b={array:"search"===f?"auto":!1},c=a.match(/\[\]$/)?{array:!0}:{};return R(b,c,e).array}function p(a,b){var c=a.squash;if(!b||c===!1)return!1;if(!L(c)||null==c)return q;if(c===!0||N(c))return c;throw new Error("Invalid squash policy: '"+c+"'. Valid policies: false, true, or arbitrary string")}function r(a,b,d,e){var f,g,i=[{from:"",to:d||b?c:""},{from:null,to:d||b?c:""}];return f=P(a.replace)?a.replace:[],N(e)&&f.push({from:e,to:c}),g=o(f,function(a){return a.from}),n(i,function(a){return-1===h(g,a.from)}).concat(f)}function t(){if(!l)throw new Error("Injectable functions cannot be called at configuration time");var a=l.invoke(e.$$fn);if(null!==a&&a!==c&&!x.type.is(a))throw new Error("Default value ("+a+") for parameter '"+x.id+"' is not an instance of Type ("+x.type.name+")");return a}function v(a){function b(a){return function(b){return b.from===a}}function c(a){var c=o(n(x.replace,b(a)),function(a){return a.to});return c.length?c[0]:a}return a=c(a),L(a)?x.type.$normalize(a):t()}function w(){return"{Param:"+a+" "+d+" squash: '"+A+"' optional: "+z+"}"}var x=this;e=j(e),d=k(e,d,f);var y=m();d=y?d.$asArray(y,"search"===f):d,"string"!==d.name||y||"path"!==f||e.value!==c||(e.value="");var z=e.value!==c,A=p(e,z),B=r(e,y,z,A);R(this,{id:a,type:d,location:f,array:y,squash:A,replace:B,isOptional:z,value:v,dynamic:c,config:e,toString:w})},k.prototype={$$new:function(){return d(this,R(new k,{$$parent:this}))},$$keys:function(){for(var a=[],b=[],c=this,d=g(k.prototype);c;)b.push(c),c=c.$$parent;return b.reverse(),Q(b,function(b){Q(g(b),function(b){-1===h(a,b)&&-1===h(d,b)&&a.push(b)})}),a},$$values:function(a){var b={},c=this;return Q(c.$$keys(),function(d){b[d]=c[d].value(a&&a[d])}),b},$$equals:function(a,b){var c=!0,d=this;return Q(d.$$keys(),function(e){var f=a&&a[e],g=b&&b[e];d[e].type.equals(f,g)||(c=!1)}),c},$$validates:function(a){var d,e,f,g,h,i=this.$$keys();for(d=0;de;e++)if(b(j[e]))return;k&&b(k)}}function o(){return i=i||e.$on("$locationChangeSuccess",n)}var p,q=g.baseHref(),r=d.url();return l||o(),{sync:function(){n()},listen:function(){return o()},update:function(a){return a?void(r=d.url()):void(d.url()!==r&&(d.url(r),d.replace()))},push:function(a,b,e){var f=a.format(b||{});null!==f&&b&&b["#"]&&(f+="#"+b["#"]),d.url(f),p=e&&e.$$avoidResync?d.url():c,e&&e.replace&&d.replace()},href:function(c,e,f){if(!c.validates(e))return null;var g=a.html5Mode();b.isObject(g)&&(g=g.enabled),g=g&&h.history;var i=c.format(e);if(f=f||{},g||null===i||(i="#"+a.hashPrefix()+i),null!==i&&e&&e["#"]&&(i+="#"+e["#"]),i=m(i,g,f.absolute),!f.absolute||!i)return i;var j=!g&&i?"/":"",k=d.port();return k=80===k||443===k?"":":"+k,[d.protocol(),"://",d.host(),k,j,i].join("")}}}var i,j=[],k=null,l=!1;this.rule=function(a){if(!M(a))throw new Error("'rule' must be a function");return j.push(a),this},this.otherwise=function(a){if(N(a)){var b=a;a=function(){return b}}else if(!M(a))throw new Error("'rule' must be a function");return k=a,this},this.when=function(a,b){var c,h=N(b);if(N(a)&&(a=d.compile(a)),!h&&!M(b)&&!P(b))throw new Error("invalid 'handler' in when()");var i={matcher:function(a,b){return h&&(c=d.compile(b),b=["$match",function(a){return c.format(a)}]),R(function(c,d){return g(c,b,a.exec(d.path(),d.search()))},{prefix:N(a.prefix)?a.prefix:""})},regex:function(a,b){if(a.global||a.sticky)throw new Error("when() RegExp must not be global or sticky");return h&&(c=b,b=["$match",function(a){return f(c,a)}]),R(function(c,d){return g(c,b,a.exec(d.path()))},{prefix:e(a)})}},j={matcher:d.isMatcher(a),regex:a instanceof RegExp};for(var k in j)if(j[k])return this.rule(i[k](a,b));throw new Error("invalid 'what' in when()")},this.deferIntercept=function(a){a===c&&(a=!0),l=a},this.$get=h,h.$inject=["$location","$rootScope","$injector","$browser","$sniffer"]}function v(a,e){function f(a){return 0===a.indexOf(".")||0===a.indexOf("^")}function m(a,b){if(!a)return c;var d=N(a),e=d?a:a.name,g=f(e);if(g){if(!b)throw new Error("No reference point given for path '"+e+"'");b=m(b);for(var h=e.split("."),i=0,j=h.length,k=b;j>i;i++)if(""!==h[i]||0!==i){if("^"!==h[i])break;if(!k.parent)throw new Error("Path '"+e+"' not valid for state '"+b.name+"'");k=k.parent}else k=b;h=h.slice(i).join("."),e=k.name+(k.name&&h?".":"")+h}var l=z[e];return!l||!d&&(d||l!==a&&l.self!==a)?c:l}function n(a,b){A[a]||(A[a]=[]),A[a].push(b)}function p(a){for(var b=A[a]||[];b.length;)q(b.shift())}function q(b){b=d(b,{self:b,resolve:b.resolve||{},toString:function(){return this.name}});var c=b.name;if(!N(c)||c.indexOf("@")>=0)throw new Error("State must have a valid name");if(z.hasOwnProperty(c))throw new Error("State '"+c+"' is already defined");var e=-1!==c.indexOf(".")?c.substring(0,c.lastIndexOf(".")):N(b.parent)?b.parent:O(b.parent)&&N(b.parent.name)?b.parent.name:"";if(e&&!z[e])return n(e,b.self);for(var f in C)M(C[f])&&(b[f]=C[f](b,C.$delegates[f]));return z[c]=b,!b[B]&&b.url&&a.when(b.url,["$match","$stateParams",function(a,c){y.$current.navigable==b&&j(a,c)||y.transitionTo(b,a,{inherit:!0,location:!1})}]),p(c),b}function r(a){return a.indexOf("*")>-1}function s(a){for(var b=a.split("."),c=y.$current.name.split("."),d=0,e=b.length;e>d;d++)"*"===b[d]&&(c[d]="*");return"**"===b[0]&&(c=c.slice(h(c,b[1])),c.unshift("**")),"**"===b[b.length-1]&&(c.splice(h(c,b[b.length-2])+1,Number.MAX_VALUE),c.push("**")),b.length!=c.length?!1:c.join("")===b.join("")}function t(a,b){return N(a)&&!L(b)?C[a]:M(b)&&N(a)?(C[a]&&!C.$delegates[a]&&(C.$delegates[a]=C[a]),C[a]=b,this):this}function u(a,b){return O(a)?b=a:b.name=a,q(b),this}function v(a,e,f,h,l,n,p,q,t){function u(b,c,d,f){var g=a.$broadcast("$stateNotFound",b,c,d);if(g.defaultPrevented)return p.update(),D;if(!g.retry)return null;if(f.$retry)return p.update(),E;var h=y.transition=e.when(g.retry);return h.then(function(){return h!==y.transition?A:(b.options.$retry=!0,y.transitionTo(b.to,b.toParams,b.options))},function(){return D}),p.update(),h}function v(a,c,d,g,i,j){function m(){var c=[];return Q(a.views,function(d,e){var g=d.resolve&&d.resolve!==a.resolve?d.resolve:{};g.$template=[function(){return f.load(e,{view:d,locals:i.globals,params:n,notify:j.notify})||""}],c.push(l.resolve(g,i.globals,i.resolve,a).then(function(c){if(M(d.controllerProvider)||P(d.controllerProvider)){var f=b.extend({},g,i.globals);c.$$controller=h.invoke(d.controllerProvider,null,f)}else c.$$controller=d.controller;c.$$state=a,c.$$controllerAs=d.controllerAs,c.$$resolveAs=d.resolveAs,i[e]=c}))}),e.all(c).then(function(){return i.globals})}var n=d?c:k(a.params.$$keys(),c),o={$stateParams:n};i.resolve=l.resolve(a.resolve,o,i.resolve,a);var p=[i.resolve.then(function(a){i.globals=a})];return g&&p.push(g),e.all(p).then(m).then(function(a){return i})}var A=e.reject(new Error("transition superseded")),C=e.reject(new Error("transition prevented")),D=e.reject(new Error("transition aborted")),E=e.reject(new Error("transition failed"));return x.locals={resolve:null,globals:{$stateParams:{}}},y={params:{},current:x.self,$current:x,transition:null},y.reload=function(a){return y.transitionTo(y.current,n,{reload:a||!0,inherit:!1,notify:!0})},y.go=function(a,b,c){return y.transitionTo(a,b,R({inherit:!0,relative:y.$current},c))},y.transitionTo=function(b,c,f){c=c||{},f=R({location:!0,inherit:!1,relative:null,notify:!0,reload:!1,$retry:!1},f||{});var g,j=y.$current,l=y.params,o=j.path,q=m(b,f.relative),r=c["#"];if(!L(q)){var s={to:b,toParams:c,options:f},t=u(s,j.self,l,f);if(t)return t;if(b=s.to,c=s.toParams,f=s.options,q=m(b,f.relative),!L(q)){if(!f.relative)throw new Error("No such state '"+b+"'");throw new Error("Could not resolve '"+b+"' from state '"+f.relative+"'")}}if(q[B])throw new Error("Cannot transition to abstract state '"+b+"'");if(f.inherit&&(c=i(n,c||{},y.$current,q)),!q.params.$$validates(c))return E;c=q.params.$$values(c),b=q;var z=b.path,D=0,F=z[D],G=x.locals,H=[];if(f.reload){if(N(f.reload)||O(f.reload)){if(O(f.reload)&&!f.reload.name)throw new Error("Invalid reload state object");var I=f.reload===!0?o[0]:m(f.reload);if(f.reload&&!I)throw new Error("No such reload state '"+(N(f.reload)?f.reload:f.reload.name)+"'");for(;F&&F===o[D]&&F!==I;)G=H[D]=F.locals,D++,F=z[D]}}else for(;F&&F===o[D]&&F.ownParams.$$equals(c,l);)G=H[D]=F.locals,D++,F=z[D];if(w(b,c,j,l,G,f))return r&&(c["#"]=r),y.params=c,S(y.params,n),S(k(b.params.$$keys(),n),b.locals.globals.$stateParams),f.location&&b.navigable&&b.navigable.url&&(p.push(b.navigable.url,c,{$$avoidResync:!0,replace:"replace"===f.location}),p.update(!0)),y.transition=null,e.when(y.current);if(c=k(b.params.$$keys(),c||{}),r&&(c["#"]=r),f.notify&&a.$broadcast("$stateChangeStart",b.self,c,j.self,l,f).defaultPrevented)return a.$broadcast("$stateChangeCancel",b.self,c,j.self,l),null==y.transition&&p.update(),C;for(var J=e.when(G),K=D;K=D;d--)g=o[d],g.self.onExit&&h.invoke(g.self.onExit,g.self,g.locals.globals),g.locals=null;for(d=D;d2?k.enter(a,null,c).then(d):k.enter(a,null,c,d)},leave:function(a,c){b.version.minor>2?k.leave(a).then(c):k.leave(a,c)}};if(j){var e=j&&j(c,a);return{enter:function(a,b,c){e.enter(a,null,b),c()},leave:function(a,b){e.leave(a),b()}}}return d()}var i=g(),j=i("$animator"),k=i("$animate"),l={restrict:"ECA",terminal:!0,priority:400,transclude:"element",compile:function(c,g,i){return function(c,g,j){function k(){if(m&&(m.remove(),m=null),o&&(o.$destroy(),o=null),n){var a=n.data("$uiViewAnim");s.leave(n,function(){a.$$animLeave.resolve(),m=null}),m=n,n=null}}function l(h){var l,m=A(c,j,g,e),t=m&&a.$current&&a.$current.locals[m];if(h||t!==p){l=c.$new(),p=a.$current.locals[m],l.$emit("$viewContentLoading",m);var u=i(l,function(a){var e=f.defer(),h=f.defer(),i={$animEnter:e.promise,$animLeave:h.promise,$$animLeave:h};a.data("$uiViewAnim",i),s.enter(a,g,function(){e.resolve(),o&&o.$emit("$viewContentAnimationEnded"),(b.isDefined(r)&&!r||c.$eval(r))&&d(a)}),k()});n=u,o=l,o.$emit("$viewContentLoaded",m),o.$eval(q)}}var m,n,o,p,q=j.onload||"",r=j.autoscroll,s=h(j,c);g.inheritedData("$uiView");c.$on("$stateChangeSuccess",function(){l(!1)}),l(!0)}}};return l}function z(a,c,d,e){return{restrict:"ECA",priority:-400,compile:function(f){var g=f.html();return function(f,h,i){var j=d.$current,k=A(f,i,h,e),l=j&&j.locals[k];if(l){h.data("$uiView",{name:k,state:l.$$state}),h.html(l.$template?l.$template:g);var m=b.extend({},l);f[l.$$resolveAs]=m;var n=a(h.contents());if(l.$$controller){l.$scope=f,l.$element=h;var o=c(l.$$controller,l);l.$$controllerAs&&(f[l.$$controllerAs]=o,f[l.$$controllerAs][l.$$resolveAs]=m),M(o.$onInit)&&o.$onInit(),h.data("$ngControllerController",o),h.children().data("$ngControllerController",o)}n(f)}}}}}function A(a,b,c,d){var e=d(b.uiView||b.name||"")(a),f=c.inheritedData("$uiView");return e.indexOf("@")>=0?e:e+"@"+(f?f.state.name:"")}function B(a,b){var c,d=a.match(/^\s*({[^}]*})\s*$/);if(d&&(a=b+"("+d[1]+")"),c=a.replace(/\n/g," ").match(/^([^(]+?)\s*(\((.*)\))?$/),!c||4!==c.length)throw new Error("Invalid state ref '"+a+"'");return{state:c[1],paramExpr:c[3]||null}}function C(a){var b=a.parent().inheritedData("$uiView");return b&&b.state&&b.state.name?b.state:void 0}function D(a){var b="[object SVGAnimatedString]"===Object.prototype.toString.call(a.prop("href")),c="FORM"===a[0].nodeName;return{attr:c?"action":b?"xlink:href":"href",isAnchor:"A"===a.prop("tagName").toUpperCase(),clickable:!c}}function E(a,b,c,d,e){return function(f){var g=f.which||f.button,h=e();if(!(g>1||f.ctrlKey||f.metaKey||f.shiftKey||a.attr("target"))){var i=c(function(){b.go(h.state,h.params,h.options)});f.preventDefault();var j=d.isAnchor&&!h.href?1:0;f.preventDefault=function(){j--<=0&&c.cancel(i)}}}}function F(a,b){return{relative:C(a)||b.$current,inherit:!0}}function G(a,c){return{restrict:"A",require:["?^uiSrefActive","?^uiSrefActiveEq"],link:function(d,e,f,g){var h,i=B(f.uiSref,a.current.name),j={state:i.state,href:null,params:null},k=D(e),l=g[1]||g[0],m=null;j.options=R(F(e,a),f.uiSrefOpts?d.$eval(f.uiSrefOpts):{});var n=function(c){c&&(j.params=b.copy(c)),j.href=a.href(i.state,j.params,j.options),m&&m(),l&&(m=l.$$addStateInfo(i.state,j.params)),null!==j.href&&f.$set(k.attr,j.href)};i.paramExpr&&(d.$watch(i.paramExpr,function(a){a!==j.params&&n(a)},!0),j.params=b.copy(d.$eval(i.paramExpr))),n(),k.clickable&&(h=E(e,a,c,k,function(){return j}),e.bind("click",h),d.$on("$destroy",function(){e.unbind("click",h)}))}}}function H(a,b){return{restrict:"A",require:["?^uiSrefActive","?^uiSrefActiveEq"],link:function(c,d,e,f){function g(b){m.state=b[0],m.params=b[1],m.options=b[2],m.href=a.href(m.state,m.params,m.options),n&&n(),j&&(n=j.$$addStateInfo(m.state,m.params)),m.href&&e.$set(i.attr,m.href)}var h,i=D(d),j=f[1]||f[0],k=[e.uiState,e.uiStateParams||null,e.uiStateOpts||null],l="["+k.map(function(a){return a||"null"}).join(", ")+"]",m={state:null,params:null,options:null,href:null},n=null;c.$watch(l,g,!0),g(c.$eval(l)),i.clickable&&(h=E(d,a,b,i,function(){return m}),d.bind("click",h),c.$on("$destroy",function(){d.unbind("click",h)}))}}}function I(a,b,c){return{restrict:"A",controller:["$scope","$element","$attrs","$timeout",function(b,d,e,f){function g(b,c,e){var f=a.get(b,C(d)),g=h(b,c),i={state:f||{name:b},params:c,hash:g};return p.push(i),q[g]=e,function(){var a=p.indexOf(i);-1!==a&&p.splice(a,1)}}function h(a,c){if(!N(a))throw new Error("state should be a string");return O(c)?a+T(c):(c=b.$eval(c),O(c)?a+T(c):a)}function i(){for(var a=0;a0)){var c=g(a,b,o);return i(),c}},b.$on("$stateChangeSuccess",i),i()}]}}function J(a){var b=function(b,c){return a.is(b,c)};return b.$stateful=!0,b}function K(a){var b=function(b,c,d){return a.includes(b,c,d)};return b.$stateful=!0,b}var L=b.isDefined,M=b.isFunction,N=b.isString,O=b.isObject,P=b.isArray,Q=b.forEach,R=b.extend,S=b.copy,T=b.toJson;b.module("ui.router.util",["ng"]),b.module("ui.router.router",["ui.router.util"]),b.module("ui.router.state",["ui.router.router","ui.router.util"]),b.module("ui.router",["ui.router.state"]),b.module("ui.router.compat",["ui.router"]),p.$inject=["$q","$injector"],b.module("ui.router.util").service("$resolve",p),q.$inject=["$http","$templateCache","$injector"],b.module("ui.router.util").service("$templateFactory",q);var U;r.prototype.concat=function(a,b){var c={caseInsensitive:U.caseInsensitive(),strict:U.strictMode(),squash:U.defaultSquashPolicy()};return new r(this.sourcePath+a+this.sourceSearch,R(c,b),this)},r.prototype.toString=function(){return this.source},r.prototype.exec=function(a,b){function c(a){function b(a){return a.split("").reverse().join("")}function c(a){return a.replace(/\\-/g,"-")}var d=b(a).split(/-(?!\\)/),e=o(d,b);return o(e,c).reverse()}var d=this.regexp.exec(a);if(!d)return null;b=b||{};var e,f,g,h=this.parameters(),i=h.length,j=this.segments.length-1,k={};if(j!==d.length-1)throw new Error("Unbalanced capture group in route '"+this.source+"'");var l,m;for(e=0;j>e;e++){for(g=h[e],l=this.params[g],m=d[e+1],f=0;fe;e++){for(g=h[e],k[g]=this.params[g].value(b[g]),l=this.params[g],m=b[g],f=0;ff;f++){var k=h>f,l=d[f],m=e[l],n=m.value(a[l]),p=m.isOptional&&m.type.equals(m.value(),n),q=p?m.squash:!1,r=m.type.encode(n);if(k){var s=c[f+1],t=f+1===h;if(q===!1)null!=r&&(j+=P(r)?o(r,b).join("-"):encodeURIComponent(r)),j+=s;else if(q===!0){var u=j.match(/\/$/)?/\/?(.*)/:/(.*)/;j+=s.match(u)[1]}else N(q)&&(j+=q+s);t&&m.squash===!0&&"/"===j.slice(-1)&&(j=j.slice(0,-1))}else{if(null==r||p&&q!==!1)continue;if(P(r)||(r=[r]),0===r.length)continue;r=o(r,encodeURIComponent).join("&"+l+"="),j+=(g?"&":"?")+(l+"="+r),g=!0}}return j},s.prototype.is=function(a,b){return!0},s.prototype.encode=function(a,b){return a},s.prototype.decode=function(a,b){return a},s.prototype.equals=function(a,b){return a==b},s.prototype.$subPattern=function(){var a=this.pattern.toString();return a.substr(1,a.length-2)},s.prototype.pattern=/.*/,s.prototype.toString=function(){return"{Type:"+this.name+"}"},s.prototype.$normalize=function(a){return this.is(a)?a:this.decode(a)},s.prototype.$asArray=function(a,b){function d(a,b){function d(a,b){return function(){return a[b].apply(a,arguments)}}function e(a){return P(a)?a:L(a)?[a]:[]}function f(a){switch(a.length){case 0:return c;case 1:return"auto"===b?a[0]:a;default:return a}}function g(a){return!a}function h(a,b){return function(c){if(P(c)&&0===c.length)return c;c=e(c);var d=o(c,a);return b===!0?0===n(d,g).length:f(d)}}function i(a){return function(b,c){var d=e(b),f=e(c);if(d.length!==f.length)return!1;for(var g=0;g0},this.rename=function(a,b){return a.ngfName=b,a},this.jsonBlob=function(a){null==a||angular.isString(a)||(a=JSON.stringify(a));var b=new window.Blob([a],{type:"application/json"});return b._ngfBlob=!0,b},this.json=function(a){return angular.toJson(a)},this.isFile=function(a){return null!=a&&(a instanceof window.Blob||a.flashId&&a.name&&a.size)},this.upload=function(a,b){function c(b,c){if(b._ngfBlob)return b;if(a._file=a._file||b,null!=a._start&&g){a._end&&a._end>=b.size&&(a._finished=!0,a._end=b.size);var d=b.slice(a._start,a._end||b.size);return d.name=b.name,d.ngfName=b.ngfName,a._chunkSize&&(c.append("_chunkSize",a._chunkSize),c.append("_currentChunkSize",a._end-a._start),c.append("_chunkNumber",Math.floor(a._start/a._chunkSize)),c.append("_totalSize",a._file.size)),d}return b}function h(b,d,e){if(void 0!==d)if(angular.isDate(d)&&(d=d.toISOString()),angular.isString(d))b.append(e,d);else if(f.isFile(d)){var g=c(d,b),i=e.split(",");i[1]&&(g.ngfName=i[1].replace(/^\s+|\s+$/g,""),e=i[0]),a._fileKey=a._fileKey||e,b.append(e,g,g.ngfName||g.name)}else if(angular.isObject(d)){if(d.$$ngfCircularDetection)throw"ngFileUpload: Circular reference in config.data. Make sure specified data for Upload.upload() has no circular reference: "+e;d.$$ngfCircularDetection=!0;try{for(var j in d)if(d.hasOwnProperty(j)&&"$$ngfCircularDetection"!==j){var k=null==a.objectKey?"[i]":a.objectKey;d.length&&parseInt(j)>-1&&(k=null==a.arrayKey?k:a.arrayKey),h(b,d[j],e+k.replace(/[ik]/g,j))}}finally{delete d.$$ngfCircularDetection}}else b.append(e,d)}function i(){a._chunkSize=f.translateScalars(a.resumeChunkSize),a._chunkSize=a._chunkSize?parseInt(a._chunkSize.toString()):null,a.headers=a.headers||{},a.headers["Content-Type"]=void 0,a.transformRequest=a.transformRequest?angular.isArray(a.transformRequest)?a.transformRequest:[a.transformRequest]:[],a.transformRequest.push(function(b){var c,d=new window.FormData;b=b||a.fields||{},a.file&&(b.file=a.file);for(c in b)if(b.hasOwnProperty(c)){var e=b[c];a.formDataAppender?a.formDataAppender(d,c,e):h(d,e,c)}return d})}return b||(a=e(a)),a._isDigested||(a._isDigested=!0,i()),d(a)},this.http=function(b){return b=e(b),b.transformRequest=b.transformRequest||function(b){return window.ArrayBuffer&&b instanceof window.ArrayBuffer||b instanceof window.Blob?b:a.defaults.transformRequest[0].apply(this,arguments)},b._chunkSize=f.translateScalars(b.resumeChunkSize),b._chunkSize=b._chunkSize?parseInt(b._chunkSize.toString()):null,d(b)},this.translateScalars=function(a){if(angular.isString(a)){if(a.search(/kb/i)===a.length-2)return parseFloat(1024*a.substring(0,a.length-2));if(a.search(/mb/i)===a.length-2)return parseFloat(1048576*a.substring(0,a.length-2));if(a.search(/gb/i)===a.length-2)return parseFloat(1073741824*a.substring(0,a.length-2));if(a.search(/b/i)===a.length-1)return parseFloat(a.substring(0,a.length-1));if(a.search(/s/i)===a.length-1)return parseFloat(a.substring(0,a.length-1));if(a.search(/m/i)===a.length-1)return parseFloat(60*a.substring(0,a.length-1));if(a.search(/h/i)===a.length-1)return parseFloat(3600*a.substring(0,a.length-1))}return a},this.urlToBlob=function(c){var d=b.defer();return a({url:c,method:"get",responseType:"arraybuffer"}).then(function(a){var b=new Uint8Array(a.data),c=a.headers("content-type")||"image/WebP",e=new window.Blob([b],{type:c});d.resolve(e)},function(a){d.reject(a)}),d.promise},this.setDefaults=function(a){this.defaults=a||{}},this.defaults={},this.version=ngFileUpload.version}]),ngFileUpload.service("Upload",["$parse","$timeout","$compile","$q","UploadExif",function(a,b,c,d,e){function f(a,b,c){var e=[i.emptyPromise()];return angular.forEach(a,function(d,f){0===d.type.indexOf("image/jpeg")&&i.attrGetter("ngfFixOrientation",b,c,{$file:d})&&e.push(i.happyPromise(i.applyExifRotation(d),d).then(function(b){a.splice(f,1,b)}))}),d.all(e)}function g(a,b,c){var e=i.attrGetter("ngfResize",b,c);if(!e||!i.isResizeSupported()||!a.length)return i.emptyPromise();if(!(e instanceof Function))return h(e,a,b,c);var f=d.defer();e(a).then(function(d){h(d,a,b,c).then(function(a){f.resolve(a)},function(a){f.reject(a)})},function(a){f.reject(a)})}function h(a,b,c,e){function f(d,f){if(0===d.type.indexOf("image")){if(a.pattern&&!i.validatePattern(d,a.pattern))return;var h=i.resize(d,a.width,a.height,a.quality,a.type,a.ratio,a.centerCrop,function(a,b){return i.attrGetter("ngfResizeIf",c,e,{$width:a,$height:b,$file:d})},a.restoreExif!==!1);g.push(h),h.then(function(a){b.splice(f,1,a)},function(a){d.$error="resize",d.$errorParam=(a?(a.message?a.message:a)+": ":"")+(d&&d.name)})}}for(var g=[i.emptyPromise()],h=0;h-1:!0},i.emptyPromise=function(){var a=d.defer(),c=arguments;return b(function(){a.resolve.apply(a,c)}),a.promise},i.rejectPromise=function(){var a=d.defer(),c=arguments;return b(function(){a.reject.apply(a,c)}),a.promise},i.happyPromise=function(a,c){var e=d.defer();return a.then(function(a){e.resolve(a)},function(a){b(function(){throw a}),e.resolve(c)}),e.promise},i.updateModel=function(c,d,e,h,j,k,l){function m(f,g,j,l,m){d.$$ngfPrevValidFiles=f,d.$$ngfPrevInvalidFiles=g;var n=f&&f.length?f[0]:null,o=g&&g.length?g[0]:null;c&&(i.applyModelValidation(c,f),c.$setViewValue(m?n:f)),h&&a(h)(e,{$files:f,$file:n,$newFiles:j,$duplicateFiles:l,$invalidFiles:g,$invalidFile:o,$event:k});var p=i.attrGetter("ngfModelInvalid",d);p&&b(function(){a(p).assign(e,m?o:g)}),b(function(){})}function n(){function a(a,b){return a.name===b.name&&(a.$ngfOrigSize||a.size)===(b.$ngfOrigSize||b.size)&&a.type===b.type}function b(b){var c;for(c=0;c2){var c=d.defaults.androidFixMinorVersion||4;return parseInt(b[1])<4||parseInt(b[1])===c&&parseInt(b[2])');n(a);var c=angular.element("upload ");return c.css("visibility","hidden").css("position","absolute").css("overflow","hidden").css("width","0px").css("height","0px").css("border","none").css("margin","0px").css("padding","0px").attr("tabindex","-1"),g.push({el:b,ref:c}),document.body.appendChild(c.append(a)[0]),a}function p(c){if(b.attr("disabled"))return!1;if(!t("ngfSelectDisabled",a)){var d=q(c);if(null!=d)return d;r(c);try{k()||document.body.contains(w[0])||(g.push({el:b,ref:w.parent()}),document.body.appendChild(w.parent()[0]),w.bind("change",m))}catch(f){}return e(navigator.userAgent)?setTimeout(function(){w[0].click()},0):w[0].click(),!1}}function q(a){var b=a.changedTouches||a.originalEvent&&a.originalEvent.changedTouches;if("touchstart"===a.type)return v=b?b[0].clientY:0,!0;if(a.stopPropagation(),a.preventDefault(),"touchend"===a.type){var c=b?b[0].clientY:0;if(Math.abs(c-v)>20)return!1}}function r(b){j.shouldUpdateOn("click",c,a)&&w.val()&&(w.val(null),j.updateModel(d,c,a,l(),null,b,!0))}function s(a){if(w&&!w.attr("__ngf_ie10_Fix_")){if(!w[0].parentNode)return void(w=null);a.preventDefault(),a.stopPropagation(),w.unbind("click");var b=w.clone();return w.replaceWith(b),w=b,w.attr("__ngf_ie10_Fix_","true"),w.bind("change",m),w.bind("click",s),w[0].click(),!1}w.removeAttr("__ngf_ie10_Fix_")}var t=function(a,b){return j.attrGetter(a,c,b)};j.registerModelChangeValidator(d,c,a);var u=[];u.push(a.$watch(t("ngfMultiple"),function(){w.attr("multiple",t("ngfMultiple",a))})),u.push(a.$watch(t("ngfCapture"),function(){w.attr("capture",t("ngfCapture",a))})),u.push(a.$watch(t("ngfAccept"),function(){w.attr("accept",t("ngfAccept",a))})),c.$observe("accept",function(){w.attr("accept",t("accept"))}),u.push(function(){c.$$observers&&delete c.$$observers.accept});var v=0,w=b;k()||(w=o()),w.bind("change",m),k()?b.bind("click",r):b.bind("click touchstart touchend",p),-1!==navigator.appVersion.indexOf("MSIE 10")&&w.bind("click",s),d&&d.$formatters.push(function(a){return(null==a||0===a.length)&&w.val()&&w.val(null),a}),a.$on("$destroy",function(){k()||w.parent().remove(),angular.forEach(u,function(a){a()})}),h(function(){for(var a=0;ab||d.blobUrls.length>e)&&d.blobUrls.length>1;){var h=d.blobUrls.splice(0,1)[0];c.revokeObjectURL(h.url),d.blobUrlsTotalSize-=h.size}}})}else{var i=new FileReader;i.onload=function(c){b(function(){a.$ngfDataUrl=c.target.result,g.resolve(c.target.result,a),b(function(){delete a.$ngfDataUrl},1e3)})},i.onerror=function(){b(function(){a.$ngfDataUrl="",g.reject()})},i.readAsDataURL(a)}}else b(function(){a[e?"$ngfDataUrl":"$ngfBlobUrl"]="",g.reject()})}),f=e?a.$$ngfDataUrlPromise=g.promise:a.$$ngfBlobUrlPromise=g.promise,f["finally"](function(){delete a[e?"$$ngfDataUrlPromise":"$$ngfBlobUrlPromise"]}),f},d}]),ngFileUpload.directive("ngfSrc",["Upload","$timeout",function(a,c){return{restrict:"AE",link:function(d,e,f){b(a,c,d,e,f,"ngfSrc",a.attrGetter("ngfResize",f,d),!1)}}}]),ngFileUpload.directive("ngfBackground",["Upload","$timeout",function(a,c){return{restrict:"AE",link:function(d,e,f){b(a,c,d,e,f,"ngfBackground",a.attrGetter("ngfResize",f,d),!0)}}}]),ngFileUpload.directive("ngfThumbnail",["Upload","$timeout",function(a,c){return{restrict:"AE",link:function(d,e,f){var g=a.attrGetter("ngfSize",f,d);b(a,c,d,e,f,"ngfThumbnail",g,a.attrGetter("ngfAsBackground",f,d))}}}]),ngFileUpload.config(["$compileProvider",function(a){a.imgSrcSanitizationWhitelist&&a.imgSrcSanitizationWhitelist(/^\s*(https?|ftp|mailto|tel|local|file|data|blob):/),a.aHrefSanitizationWhitelist&&a.aHrefSanitizationWhitelist(/^\s*(https?|ftp|mailto|tel|local|file|data|blob):/)}]),ngFileUpload.filter("ngfDataUrl",["UploadDataUrl","$sce",function(a,b){return function(c,d,e){if(angular.isString(c))return b.trustAsResourceUrl(c);var f=c&&((d?c.$ngfDataUrl:c.$ngfBlobUrl)||c.$ngfDataUrl);return c&&!f?(!c.$ngfDataUrlFilterInProgress&&angular.isObject(c)&&(c.$ngfDataUrlFilterInProgress=!0,a.dataUrl(c,d)),""):(c&&delete c.$ngfDataUrlFilterInProgress,(c&&f?e?b.trustAsResourceUrl(f):f:c)||"")}}])}(),ngFileUpload.service("UploadValidate",["UploadDataUrl","$q","$timeout",function(a,b,c){function d(a){var b="",c=[];if(a.length>2&&"/"===a[0]&&"/"===a[a.length-1])b=a.substring(1,a.length-1);else{var e=a.split(",");if(e.length>1)for(var f=0;f|:\\-]","g"),"\\$&")+"$",b=b.replace(/\\\*/g,".*").replace(/\\\?/g,"."))}return{regexp:b,excludes:c}}function e(a,b){null==b||a.$dirty||(a.$setDirty?a.$setDirty():a.$dirty=!0)}var f=a;return f.validatePattern=function(a,b){if(!b)return!0;var c=d(b),e=!0;if(c.regexp&&c.regexp.length){var f=new RegExp(c.regexp,"i");e=null!=a.type&&f.test(a.type)||null!=a.name&&f.test(a.name)}for(var g=c.excludes.length;g--;){var h=new RegExp(c.excludes[g],"i");e=e&&(null==a.type||h.test(a.type))&&(null==a.name||h.test(a.name))}return e},f.ratioToFloat=function(a){var b=a.toString(),c=b.search(/[x:]/i);return b=c>-1?parseFloat(b.substring(0,c))/parseFloat(b.substring(c+1)):parseFloat(b)},f.registerModelChangeValidator=function(a,b,c){a&&a.$formatters.push(function(d){a.$dirty&&(d&&!angular.isArray(d)&&(d=[d]),f.validate(d,0,a,b,c).then(function(){f.applyModelValidation(a,d)}))})},f.applyModelValidation=function(a,b){e(a,b),angular.forEach(a.$ngfValidations,function(b){a.$setValidity(b.name,b.valid)})},f.getValidationAttr=function(a,b,c,d,e){var g="ngf"+c[0].toUpperCase()+c.substr(1),h=f.attrGetter(g,a,b,{$file:e});if(null==h&&(h=f.attrGetter("ngfValidate",a,b,{$file:e}))){var i=(d||c).split(".");h=h[i[0]],i.length>1&&(h=h&&h[i[1]])}return h},f.validate=function(a,c,d,e,g){function h(b,c,h){if(a){for(var i=a.length,j=null;i--;){var k=a[i];if(k){var l=f.getValidationAttr(e,g,b,c,k);null!=l&&(h(k,l,i)||(k.$error=b,(k.$errorMessages=k.$errorMessages||{})[b]=!0,k.$errorParam=l,a.splice(i,1),j=!1))}}null!==j&&d.$ngfValidations.push({name:b,valid:j})}}function i(c,h,i,k,l){function m(a,b,d){null!=d?k(b,d).then(function(e){l(e,d)?a.resolve():(b.$error=c,(b.$errorMessages=b.$errorMessages||{})[c]=!0,b.$errorParam=d,a.reject())},function(){j("ngfValidateForce",{$file:b})?(b.$error=c,(b.$errorMessages=b.$errorMessages||{})[c]=!0,b.$errorParam=d,a.reject()):a.resolve()}):a.resolve()}var n=[f.emptyPromise()];return a?(a=void 0===a.length?[a]:a,angular.forEach(a,function(a){var d=b.defer();return n.push(d.promise),!i||null!=a.type&&0===a.type.search(i)?void("dimensions"===c&&null!=f.attrGetter("ngfDimensions",e)?f.imageDimensions(a).then(function(b){m(d,a,j("ngfDimensions",{$file:a,$width:b.width,$height:b.height}))},function(){d.reject()}):"duration"===c&&null!=f.attrGetter("ngfDuration",e)?f.mediaDuration(a).then(function(b){m(d,a,j("ngfDuration",{$file:a,$duration:b}))},function(){d.reject()}):m(d,a,f.getValidationAttr(e,g,c,h,a))):void d.resolve()}),b.all(n).then(function(){d.$ngfValidations.push({name:c,valid:!0})},function(){d.$ngfValidations.push({name:c,valid:!1})})):void 0}d=d||{},d.$ngfValidations=d.$ngfValidations||[],angular.forEach(d.$ngfValidations,function(a){a.valid=!0});var j=function(a,b){return f.attrGetter(a,e,g,b)};if(null==a||0===a.length)return f.emptyPromise(d);a=void 0===a.length?[a]:a.slice(0),h("maxFiles",null,function(a,b,d){return b>c+d}),h("pattern",null,f.validatePattern),h("minSize","size.min",function(a,b){return a.size+.1>=f.translateScalars(b)}),h("maxSize","size.max",function(a,b){return a.size-.1<=f.translateScalars(b)});var k=0;if(h("maxTotalSize",null,function(b,c){return k+=b.size,k>f.translateScalars(c)?(a.splice(0,a.length),!1):!0}),h("validateFn",null,function(a,b){return b===!0||null===b||""===b}),!a.length)return f.emptyPromise(d,d.$ngfValidations);var l=b.defer(),m=[];return m.push(f.happyPromise(i("maxHeight","height.max",/image/,this.imageDimensions,function(a,b){return a.height<=b}))),m.push(f.happyPromise(i("minHeight","height.min",/image/,this.imageDimensions,function(a,b){return a.height>=b}))),m.push(f.happyPromise(i("maxWidth","width.max",/image/,this.imageDimensions,function(a,b){return a.width<=b}))),m.push(f.happyPromise(i("minWidth","width.min",/image/,this.imageDimensions,function(a,b){return a.width>=b}))),m.push(f.happyPromise(i("dimensions",null,/image/,function(a,b){return f.emptyPromise(b)},function(a){return a}))),m.push(f.happyPromise(i("ratio",null,/image/,this.imageDimensions,function(a,b){for(var c=b.toString().split(","),d=!1,e=0;e-1e-4}))),m.push(f.happyPromise(i("maxDuration","duration.max",/audio|video/,this.mediaDuration,function(a,b){return a<=f.translateScalars(b)}))),m.push(f.happyPromise(i("minDuration","duration.min",/audio|video/,this.mediaDuration,function(a,b){return a>=f.translateScalars(b)}))),m.push(f.happyPromise(i("duration",null,/audio|video/,function(a,b){return f.emptyPromise(b)},function(a){return a}))),m.push(f.happyPromise(i("validateAsyncFn",null,null,function(a,b){return b},function(a){return a===!0||null===a||""===a}))),b.all(m).then(function(){l.resolve(d,d.$ngfValidations)})},f.imageDimensions=function(a){if(a.$ngfWidth&&a.$ngfHeight){var d=b.defer();return c(function(){d.resolve({width:a.$ngfWidth,height:a.$ngfHeight})}),d.promise}if(a.$ngfDimensionPromise)return a.$ngfDimensionPromise;var e=b.defer();return c(function(){return 0!==a.type.indexOf("image")?void e.reject("not image"):void f.dataUrl(a).then(function(b){function d(){var b=h[0].clientWidth,c=h[0].clientHeight;h.remove(),a.$ngfWidth=b,a.$ngfHeight=c,e.resolve({width:b,height:c})}function f(){h.remove(),e.reject("load error")}function g(){c(function(){h[0].parentNode&&(h[0].clientWidth?d():i>10?f():g())},1e3)}var h=angular.element(" ").attr("src",b).css("visibility","hidden").css("position","fixed").css("max-width","none !important").css("max-height","none !important");h.on("load",d),h.on("error",f);var i=0;g(),angular.element(document.getElementsByTagName("body")[0]).append(h)},function(){e.reject("load error")})}),a.$ngfDimensionPromise=e.promise,a.$ngfDimensionPromise["finally"](function(){delete a.$ngfDimensionPromise}),a.$ngfDimensionPromise},f.mediaDuration=function(a){if(a.$ngfDuration){var d=b.defer();return c(function(){d.resolve(a.$ngfDuration)}),d.promise}if(a.$ngfDurationPromise)return a.$ngfDurationPromise;var e=b.defer();return c(function(){return 0!==a.type.indexOf("audio")&&0!==a.type.indexOf("video")?void e.reject("not media"):void f.dataUrl(a).then(function(b){function d(){var b=h[0].duration;a.$ngfDuration=b,h.remove(),e.resolve(b)}function f(){h.remove(),e.reject("load error")}function g(){c(function(){h[0].parentNode&&(h[0].duration?d():i>10?f():g())},1e3)}var h=angular.element(0===a.type.indexOf("audio")?"":"").attr("src",b).css("visibility","none").css("position","fixed");h.on("loadedmetadata",d),h.on("error",f);var i=0;g(),angular.element(document.body).append(h)},function(){e.reject("load error")})}),a.$ngfDurationPromise=e.promise,a.$ngfDurationPromise["finally"](function(){delete a.$ngfDurationPromise}),a.$ngfDurationPromise},f}]),ngFileUpload.service("UploadResize",["UploadValidate","$q",function(a,b){var c=a,d=function(a,b,c,d,e){var f=e?Math.max(c/a,d/b):Math.min(c/a,d/b);return{width:a*f,height:b*f,marginX:a*f-c,marginY:b*f-d}},e=function(a,e,f,g,h,i,j,k){var l=b.defer(),m=document.createElement("canvas"),n=document.createElement("img");return n.onload=function(){if(null!=k&&k(n.width,n.height)===!1)return void l.reject("resizeIf");try{if(i){var a=c.ratioToFloat(i),b=n.width/n.height;a>b?(e=n.width,f=e/a):(f=n.height,e=f*a)}e||(e=n.width),f||(f=n.height);var o=d(n.width,n.height,e,f,j);m.width=Math.min(o.width,e),m.height=Math.min(o.height,f);var p=m.getContext("2d");p.drawImage(n,Math.min(0,-o.marginX/2),Math.min(0,-o.marginY/2),o.width,o.height),l.resolve(m.toDataURL(h||"image/WebP",g||.934))}catch(q){l.reject(q)}},n.onerror=function(){l.reject()},n.src=a,l.promise};return c.dataUrltoBlob=function(a,b,c){for(var d=a.split(","),e=d[0].match(/:(.*?);/)[1],f=atob(d[1]),g=f.length,h=new Uint8Array(g);g--;)h[g]=f.charCodeAt(g);var i=new window.Blob([h],{type:e});return i.name=b,i.$ngfOrigSize=c,i},c.isResizeSupported=function(){var a=document.createElement("canvas");return window.atob&&a.getContext&&a.getContext("2d")&&window.Blob},c.isResizeSupported()&&Object.defineProperty(window.Blob.prototype,"name",{get:function(){return this.$ngfName},set:function(a){this.$ngfName=a},configurable:!0}),c.resize=function(a,d,f,g,h,i,j,k,l){if(0!==a.type.indexOf("image"))return c.emptyPromise(a);var m=b.defer();return c.dataUrl(a,!0).then(function(b){e(b,d,f,g,h||a.type,i,j,k).then(function(d){if("image/jpeg"===a.type&&l)try{d=c.restoreExif(b,d)}catch(e){setTimeout(function(){throw e},1)}try{var f=c.dataUrltoBlob(d,a.name,a.size);m.resolve(f)}catch(e){m.reject(e)}},function(b){"resizeIf"===b&&m.resolve(a),m.reject(b)})},function(a){m.reject(a)}),m.promise},c}]),function(){function a(a,c,d,e,f,g,h,i,j,k){function l(){return c.attr("disabled")||r("ngfDropDisabled",a)}function m(b,c){i.updateModel(e,d,a,r("ngfChange")||r("ngfDrop"),b,c)}function n(b,c){if(!i.shouldUpdateOn(b,d,a)||!c)return i.rejectPromise([]);var e=[];c.replace(/<(img src|img [^>]* src) *=\"([^\"]*)\"/gi,function(a,b,c){e.push(c)});var f=[],g=[];if(e.length){angular.forEach(e,function(a){f.push(i.urlToBlob(a).then(function(a){g.push(a)}))});var h=k.defer();return k.all(f).then(function(){h.resolve(g)},function(a){h.reject(a)}),h.promise}return i.emptyPromise()}function o(a,b,c,d){var e=r("ngfDragOverClass",a,{$event:c}),f="dragover";if(angular.isString(e))f=e;else if(e&&(e.delay&&(v=e.delay),e.accept||e.reject)){var g=c.dataTransfer.items;if(null!=g&&g.length)for(var h=e.pattern||r("ngfPattern",a,{$event:c}),j=g.length;j--;){if(!i.validatePattern(g[j],h)){f=e.reject;break}f=e.accept}else f=e.accept}d(f)}function p(b,c,e,f){function g(a,b){var c=k.defer();if(null!=a)if(a.isDirectory){var d=[i.emptyPromise()];if(m){var e={type:"directory"};e.name=e.path=(b||"")+a.name+a.name,n.push(e)}var f=a.createReader(),h=[],p=function(){f.readEntries(function(e){try{e.length?(h=h.concat(Array.prototype.slice.call(e||[],0)),p()):(angular.forEach(h.slice(0),function(c){n.length<=j&&l>=o&&d.push(g(c,(b?b:"")+a.name+"/"))}),k.all(d).then(function(){c.resolve()},function(a){c.reject(a)}))}catch(f){c.reject(f)}},function(a){c.reject(a)})};p()}else a.file(function(a){try{a.path=(b?b:"")+a.name,m&&(a=i.rename(a,a.path)),n.push(a),o+=a.size,c.resolve()}catch(d){c.reject(d)}},function(a){c.reject(a)});return c.promise}var j=i.getValidationAttr(d,a,"maxFiles")||Number.MAX_VALUE,l=i.getValidationAttr(d,a,"maxTotalSize")||Number.MAX_VALUE,m=r("ngfIncludeDir",a),n=[],o=0,p=[i.emptyPromise()];if(b&&b.length>0&&"file"!==h.protocol())for(var q=0;qj||o>l||!f&&n.length>0)break}else if(null!=c)for(var u=0;u0)&&(n.push(v),o+=v.size),n.length>j||o>l||!f&&n.length>0)break}var w=k.defer();return k.all(p).then(function(){if(f||m||!n.length)w.resolve(n);else{for(var a=0;n[a]&&"directory"===n[a].type;)a++;w.resolve([n[a]])}},function(a){w.reject(a)}),w.promise}var q=b(),r=function(a,b,c){return i.attrGetter(a,d,b,c)};if(r("dropAvailable")&&g(function(){a[r("dropAvailable")]?a[r("dropAvailable")].value=q:a[r("dropAvailable")]=q}),!q)return void(r("ngfHideOnDropNotAvailable",a)===!0&&c.css("display","none"));null==r("ngfSelect")&&i.registerModelChangeValidator(e,d,a);var s,t=null,u=f(r("ngfStopPropagation")),v=1;c[0].addEventListener("dragover",function(b){if(!l()&&i.shouldUpdateOn("drop",d,a)){if(b.preventDefault(),u(a)&&b.stopPropagation(),navigator.userAgent.indexOf("Chrome")>-1){var e=b.dataTransfer.effectAllowed;b.dataTransfer.dropEffect="move"===e||"linkMove"===e?"move":"copy"}g.cancel(t),s||(s="C",o(a,d,b,function(d){s=d,c.addClass(s),r("ngfDrag",a,{$isDragging:!0,$class:s,$event:b})}))}},!1),c[0].addEventListener("dragenter",function(b){!l()&&i.shouldUpdateOn("drop",d,a)&&(b.preventDefault(),u(a)&&b.stopPropagation())},!1),c[0].addEventListener("dragleave",function(b){!l()&&i.shouldUpdateOn("drop",d,a)&&(b.preventDefault(),u(a)&&b.stopPropagation(),t=g(function(){s&&c.removeClass(s),s=null,r("ngfDrag",a,{$isDragging:!1,$event:b})},v||100))},!1),c[0].addEventListener("drop",function(b){if(!l()&&i.shouldUpdateOn("drop",d,a)){b.preventDefault(),u(a)&&b.stopPropagation(),s&&c.removeClass(s),s=null;var e,f=b.dataTransfer.items;try{e=b.dataTransfer&&b.dataTransfer.getData&&b.dataTransfer.getData("text/html")}catch(g){}p(f,b.dataTransfer.files,r("ngfAllowDir",a)!==!1,r("multiple")||r("ngfMultiple",a)).then(function(a){a.length?m(a,b):n("dropUrl",e).then(function(a){m(a,b)})})}},!1),c[0].addEventListener("paste",function(b){if(navigator.userAgent.toLowerCase().indexOf("firefox")>-1&&r("ngfEnableFirefoxPaste",a)&&b.preventDefault(),!l()&&i.shouldUpdateOn("paste",d,a)){var c=[],e=b.clipboardData||b.originalEvent.clipboardData;if(e&&e.items)for(var f=0;f-1&&r("ngfEnableFirefoxPaste",a)&&(c.attr("contenteditable",!0),c.on("keypress",function(a){a.metaKey||a.ctrlKey||a.preventDefault()}))}function b(){var a=document.createElement("div");return"draggable"in a&&"ondrop"in a&&!/Edge\/12./i.test(navigator.userAgent)}ngFileUpload.directive("ngfDrop",["$parse","$timeout","$location","Upload","$http","$q",function(b,c,d,e,f,g){
3 | return{restrict:"AEC",require:"?ngModel",link:function(h,i,j,k){a(h,i,j,k,b,c,d,e,f,g)}}}]),ngFileUpload.directive("ngfNoFileDrop",function(){return function(a,c){b()&&c.css("display","none")}}),ngFileUpload.directive("ngfDropAvailable",["$parse","$timeout","Upload",function(a,c,d){return function(e,f,g){if(b()){var h=a(d.attrGetter("ngfDropAvailable",g));c(function(){h(e),h.assign&&h.assign(e,!0)})}}}])}(),ngFileUpload.service("UploadExif",["UploadResize","$q",function(a,b){function c(a,b,c,d){switch(b){case 2:return a.transform(-1,0,0,1,c,0);case 3:return a.transform(-1,0,0,-1,c,d);case 4:return a.transform(1,0,0,-1,0,d);case 5:return a.transform(0,1,1,0,0,0);case 6:return a.transform(0,1,-1,0,d,0);case 7:return a.transform(0,-1,-1,0,d,c);case 8:return a.transform(0,-1,1,0,0,c)}}function d(a){for(var b="",c=new Uint8Array(a),d=c.byteLength,e=0;d>e;e++)b+=String.fromCharCode(c[e]);return window.btoa(b)}var e=a;return e.isExifSupported=function(){return window.FileReader&&(new FileReader).readAsArrayBuffer&&e.isResizeSupported()},e.readOrientation=function(a){var c=b.defer(),d=new FileReader,e=a.slice?a.slice(0,65536):a;return d.readAsArrayBuffer(e),d.onerror=function(a){return c.reject(a)},d.onload=function(a){var b={orientation:1},d=new DataView(this.result);if(65496!==d.getUint16(0,!1))return c.resolve(b);for(var e=d.byteLength,f=2;e>f;){var g=d.getUint16(f,!1);if(f+=2,65505===g){if(1165519206!==d.getUint32(f+=2,!1))return c.resolve(b);var h=18761===d.getUint16(f+=6,!1);f+=d.getUint32(f+4,h);var i=d.getUint16(f,h);f+=2;for(var j=0;i>j;j++)if(274===d.getUint16(f+12*j,h)){var k=d.getUint16(f+12*j+8,h);return k>=2&&8>=k&&(d.setUint16(f+12*j+8,1,h),b.fixedArrayBuffer=a.target.result),b.orientation=k,c.resolve(b)}}else{if(65280!==(65280&g))break;f+=d.getUint16(f,!1)}}return c.resolve(b)},c.promise},e.applyExifRotation=function(a){if(0!==a.type.indexOf("image/jpeg"))return e.emptyPromise(a);var f=b.defer();return e.readOrientation(a).then(function(b){return b.orientation<2||b.orientation>8?f.resolve(a):void e.dataUrl(a,!0).then(function(g){var h=document.createElement("canvas"),i=document.createElement("img");i.onload=function(){try{h.width=b.orientation>4?i.height:i.width,h.height=b.orientation>4?i.width:i.height;var g=h.getContext("2d");c(g,b.orientation,i.width,i.height),g.drawImage(i,0,0);var j=h.toDataURL(a.type||"image/WebP",.934);j=e.restoreExif(d(b.fixedArrayBuffer),j);var k=e.dataUrltoBlob(j,a.name);f.resolve(k)}catch(l){return f.reject(l)}},i.onerror=function(){f.reject()},i.src=g},function(a){f.reject(a)})},function(a){f.reject(a)}),f.promise},e.restoreExif=function(a,b){var c={};return c.KEY_STR="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",c.encode64=function(a){var b,c,d,e,f,g="",h="",i="",j=0;do b=a[j++],c=a[j++],h=a[j++],d=b>>2,e=(3&b)<<4|c>>4,f=(15&c)<<2|h>>6,i=63&h,isNaN(c)?f=i=64:isNaN(h)&&(i=64),g=g+this.KEY_STR.charAt(d)+this.KEY_STR.charAt(e)+this.KEY_STR.charAt(f)+this.KEY_STR.charAt(i),b=c=h="",d=e=f=i="";while(ja.length)break}return c},c.decode64=function(a){var b,c,d,e,f,g="",h="",i=0,j=[],k=/[^A-Za-z0-9\+\/\=]/g;k.exec(a)&&console.log("There were invalid base64 characters in the input text.\nValid base64 characters are A-Z, a-z, 0-9, NaNExpect errors in decoding."),a=a.replace(/[^A-Za-z0-9\+\/\=]/g,"");do d=this.KEY_STR.indexOf(a.charAt(i++)),e=this.KEY_STR.indexOf(a.charAt(i++)),f=this.KEY_STR.indexOf(a.charAt(i++)),h=this.KEY_STR.indexOf(a.charAt(i++)),b=d<<2|e>>4,c=(15&e)<<4|f>>2,g=(3&f)<<6|h,j.push(b),64!==f&&j.push(c),64!==h&&j.push(g),b=c=g="",d=e=f=h="";while(i