├── .gitignore ├── Labs ├── Creating Application Factories-Services │ ├── End │ │ └── Readme.txt │ └── Files │ │ └── CustomerManager │ │ └── app │ │ └── customersApp │ │ ├── app.js │ │ └── services │ │ ├── authService.js │ │ ├── config.js │ │ ├── customersService.js │ │ └── dataService.js ├── Creating Custom Directives │ ├── End │ │ ├── Readme.txt │ │ └── index.html │ └── Files │ │ └── CustomerManager │ │ ├── app │ │ ├── customersApp │ │ │ ├── directives │ │ │ │ └── wcUnique.js │ │ │ └── views │ │ │ │ └── customers │ │ │ │ └── customerEdit.html │ │ └── wc.directives │ │ │ └── directives │ │ │ └── wcOverlay.js │ │ └── index.html ├── Creating a Module Factory Controller and View │ ├── Begin │ │ ├── app │ │ │ └── views │ │ │ │ ├── customers.html │ │ │ │ └── orders.html │ │ ├── index.html │ │ ├── js │ │ │ ├── angular-animate.js │ │ │ ├── angular-route.js │ │ │ └── angular.js │ │ ├── package.json │ │ ├── server.js │ │ ├── snippets.js │ │ └── styles │ │ │ └── animations.css │ └── End │ │ ├── app │ │ └── views │ │ │ ├── customers.html │ │ │ └── orders.html │ │ ├── index.html │ │ ├── package.json │ │ ├── server.js │ │ ├── snippets.js │ │ └── styles │ │ └── animations.css ├── Creating the CustomersController and View │ ├── End │ │ └── Readme.txt │ └── Files │ │ └── CustomerManager │ │ └── app │ │ └── customersApp │ │ ├── controllers │ │ └── customers │ │ │ └── customersController.js │ │ └── views │ │ └── customers │ │ └── customers.html ├── Creating the LoginController and View │ ├── End │ │ └── Readme.txt │ └── Files │ │ └── CustomerManager │ │ ├── Content │ │ └── styles.css │ │ └── app │ │ └── customersApp │ │ ├── controllers │ │ └── loginController.js │ │ └── views │ │ └── login.html ├── Creating the NavbarController and View │ ├── End │ │ └── Readme.txt │ └── Files │ │ └── CustomerManager │ │ ├── app │ │ └── customersApp │ │ │ └── controllers │ │ │ └── navbarController.js │ │ └── index.html ├── Defining Application Routes │ ├── End │ │ └── Readme.txt │ └── Files │ │ └── CustomerManager │ │ ├── app │ │ └── customersApp │ │ │ └── app.js │ │ └── index.html ├── Unit Testing AngularJS Components │ ├── Begin │ │ ├── app │ │ │ ├── app.js │ │ │ ├── css │ │ │ │ ├── .gitkeep │ │ │ │ └── app.css │ │ │ ├── lib │ │ │ │ ├── angular-animate.js │ │ │ │ ├── angular-mocks.js │ │ │ │ ├── angular-route.js │ │ │ │ ├── angular.js │ │ │ │ └── jasmine │ │ │ │ │ ├── MIT.LICENSE │ │ │ │ │ ├── boot.js │ │ │ │ │ ├── console.js │ │ │ │ │ ├── jasmine-html.js │ │ │ │ │ ├── jasmine.css │ │ │ │ │ ├── jasmine.js │ │ │ │ │ └── jasmine_favicon.png │ │ │ └── reminders.html │ │ ├── package.json │ │ ├── server.js │ │ └── test │ │ │ └── unit │ │ │ └── servicesSpec.js │ └── End │ │ ├── app │ │ ├── app.js │ │ ├── css │ │ │ └── app.css │ │ ├── lib │ │ │ ├── angular-animate.js │ │ │ ├── angular-mocks.js │ │ │ ├── angular-route.js │ │ │ ├── angular.js │ │ │ └── jasmine │ │ │ │ ├── MIT.LICENSE │ │ │ │ ├── boot.js │ │ │ │ ├── console.js │ │ │ │ ├── jasmine-html.js │ │ │ │ ├── jasmine.css │ │ │ │ ├── jasmine.js │ │ │ │ └── jasmine_favicon.png │ │ └── reminders.html │ │ ├── karma.conf.js │ │ ├── package.json │ │ ├── server.js │ │ └── test │ │ └── unit │ │ ├── controllersSpec.js │ │ └── servicesSpec.js └── Working with Controllers and Watches │ ├── Begin │ └── index.html │ └── End │ └── index.html ├── Samples ├── AngularJSStarterDemo │ ├── app │ │ └── views │ │ │ ├── customers.html │ │ │ └── orders.html │ ├── customers.json │ ├── index.html │ ├── js │ │ ├── angular-animate.js │ │ ├── angular-route.js │ │ └── angular.js │ ├── package.json │ ├── server.js │ ├── snippets.js │ └── styles │ │ └── animations.css ├── BroadcastAndEmit │ └── index.html ├── Directives │ ├── compile.html │ ├── component.html │ ├── controller.html │ ├── controllerAs.html │ ├── controllerNotUsed.html │ ├── controllerPassingParameter1.html │ ├── controllerPassingParameter2.html │ ├── customDirective.html │ ├── isolateScope.html │ ├── isolateScopeWithModel.html │ ├── isolateScopeWithModelAndElement.html │ ├── isolateScopeWithModelAndEvent.html │ ├── isolateScopeWithModelEventAndArray.html │ ├── isolateScopeWithString.html │ ├── js │ │ ├── compileDirective.js │ │ ├── component.js │ │ ├── controllerAsDirective.js │ │ ├── controllerDirective.js │ │ ├── controllerNotUsed.js │ │ ├── controllerPassingParameter1Directive.js │ │ ├── controllerPassingParameter2Directive.js │ │ ├── directivesController.js │ │ ├── isolateScopeDirective.js │ │ ├── isolateScopeWithModelAndElementDirective.js │ │ ├── isolateScopeWithModelAndEventDirective.js │ │ ├── isolateScopeWithModelDirective.js │ │ ├── isolateScopeWithModelEventAndArrayDirective.js │ │ ├── isolateScopeWithStringDirective.js │ │ ├── lazyLoadDirective.js │ │ ├── linkDirective.js │ │ ├── mapGeoLocationDirective.js │ │ ├── sharedScopeDirective.js │ │ ├── tableHelperControllerDirective.js │ │ ├── tableHelperDOMDirective.js │ │ ├── tableHelperDOMWithNgModelDirective.js │ │ ├── tableHelperDOMWithParseDirective.js │ │ └── transclusionDirective.js │ ├── lazyLoad.html │ ├── link.html │ ├── mapGeoLocation.html │ ├── sharedScope.html │ ├── tableHelperController.html │ ├── tableHelperDOM.html │ ├── tableHelperDOMWithParse.html │ ├── tableHelperDomWithNgModel.html │ └── transclusion.html ├── HybridSPADemo │ ├── .nuget │ │ ├── NuGet.Config │ │ ├── NuGet.exe │ │ └── NuGet.targets │ ├── HybridSPADemo.sln │ └── HybridSPADemo │ │ ├── App_Start │ │ └── RouteConfig.cs │ │ ├── Controllers │ │ └── ViewsController.cs │ │ ├── Global.asax │ │ ├── Global.asax.cs │ │ ├── HybridSPADemo.csproj │ │ ├── HybridSPADemo.csproj.user │ │ ├── Properties │ │ └── AssemblyInfo.cs │ │ ├── Scripts │ │ ├── jquery-1.10.2.intellisense.js │ │ ├── jquery-1.10.2.js │ │ ├── jquery-1.10.2.min.js │ │ ├── jquery-1.10.2.min.map │ │ ├── jquery.validate-vsdoc.js │ │ ├── jquery.validate.js │ │ ├── jquery.validate.min.js │ │ ├── jquery.validate.unobtrusive.js │ │ └── jquery.validate.unobtrusive.min.js │ │ ├── Views │ │ ├── Shared │ │ │ ├── _Layout.cshtml │ │ │ └── _ViewsLayout.cshtml │ │ ├── Views │ │ │ └── Orders.cshtml │ │ ├── _ViewStart.cshtml │ │ └── web.config │ │ ├── Web.Debug.config │ │ ├── Web.Release.config │ │ ├── Web.config │ │ ├── app │ │ └── views │ │ │ ├── customers.html │ │ │ └── orders.html │ │ ├── customers.txt │ │ ├── index.html │ │ ├── js │ │ ├── angular-animate.js │ │ ├── angular-route.js │ │ └── angular.js │ │ ├── packages.config │ │ └── styles │ │ └── animations.css ├── Pagination │ └── index.html ├── Routing │ ├── RoutingExample │ │ ├── Web.config │ │ ├── app │ │ │ ├── app.js │ │ │ ├── controllers │ │ │ │ ├── customersController.js │ │ │ │ └── ordersController.js │ │ │ ├── services │ │ │ │ ├── customersService.js │ │ │ │ └── ordersService.js │ │ │ └── views │ │ │ │ ├── customers.html │ │ │ │ └── orders.html │ │ ├── customers.json │ │ ├── index.html │ │ ├── orders.json │ │ ├── package.json │ │ ├── server.js │ │ ├── snippets.js │ │ └── styles │ │ │ └── animations.css │ └── ui-router │ │ ├── README.md │ │ ├── app.js │ │ ├── colors-list.html │ │ ├── customer-details.html │ │ ├── customers.html │ │ ├── home.html │ │ ├── index.html │ │ ├── package.json │ │ └── server.js ├── Scopes │ └── index.html ├── UnitTesting │ ├── app │ │ ├── app.js │ │ ├── css │ │ │ ├── .gitkeep │ │ │ └── app.css │ │ ├── lib │ │ │ ├── angular-animate.js │ │ │ ├── angular-mocks.js │ │ │ ├── angular-route.js │ │ │ ├── angular.js │ │ │ └── jasmine │ │ │ │ ├── MIT.LICENSE │ │ │ │ ├── boot.js │ │ │ │ ├── console.js │ │ │ │ ├── jasmine-html.js │ │ │ │ ├── jasmine.css │ │ │ │ ├── jasmine.js │ │ │ │ └── jasmine_favicon.png │ │ └── reminders.html │ ├── package.json │ ├── server.js │ └── test │ │ ├── karma.conf.js │ │ └── unit │ │ ├── controllersSpec.js │ │ ├── directivesSpec.js │ │ ├── filtersSpec.js │ │ └── servicesSpec.js └── Watches │ └── index.html ├── Src ├── .nuget │ ├── NuGet.Config │ ├── NuGet.exe │ └── NuGet.targets ├── .vs │ └── config │ │ └── applicationhost.config ├── CustomerManager.sln ├── CustomerManager │ ├── App_Start │ │ ├── BreezeWebApiConfig.cs │ │ └── WebApiConfig.cs │ ├── Content │ │ ├── animations.css │ │ ├── bootstrap.css │ │ ├── bootstrap.icon-large.min.css │ │ ├── images │ │ │ ├── ColorPalette.png │ │ │ ├── CourseLogoYellow.png │ │ │ ├── angularShield.png │ │ │ ├── appFolders.png │ │ │ ├── customerApp.png │ │ │ ├── favicon.ico │ │ │ ├── female.png │ │ │ ├── male.png │ │ │ ├── people.png │ │ │ ├── report.png │ │ │ └── spinner.gif │ │ └── styles.css │ ├── Controllers │ │ ├── BreezeDataServiceController.cs │ │ └── DataServiceController.cs │ ├── CustomerManager.csproj │ ├── CustomerManager.csproj.user │ ├── Global.asax │ ├── Global.asax.cs │ ├── Model │ │ ├── Customer.cs │ │ ├── CustomerSummary.cs │ │ ├── OperationStatus.cs │ │ ├── Order.cs │ │ ├── State.cs │ │ └── UserLogin.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── Repository │ │ ├── CustomerManagerContext.cs │ │ ├── CustomerManagerDatabaseInitializer.cs │ │ ├── CustomerRepository.cs │ │ └── DataInitializer.cs │ ├── Scripts │ │ ├── angular-ui-bootstrap.js │ │ ├── breeze.angular.js │ │ ├── breeze.debug.js │ │ ├── breeze.min.js │ │ └── tweenMax.min.js │ ├── Web.Debug.config │ ├── Web.Release.config │ ├── Web.config │ ├── app │ │ ├── customersApp │ │ │ ├── animations │ │ │ │ └── listAnimations.js │ │ │ ├── app.js │ │ │ ├── controllers │ │ │ │ ├── aboutController.js │ │ │ │ ├── customers │ │ │ │ │ ├── customerEditController.js │ │ │ │ │ ├── customerOrdersController.js │ │ │ │ │ └── customersController.js │ │ │ │ ├── loginController.js │ │ │ │ ├── navbarController.js │ │ │ │ └── orders │ │ │ │ │ ├── orderChildController.js │ │ │ │ │ └── ordersController.js │ │ │ ├── directives │ │ │ │ ├── lazyLoader.js │ │ │ │ └── wcUnique.js │ │ │ ├── filters │ │ │ │ ├── nameCityStateFilter.js │ │ │ │ └── nameProductFilter.js │ │ │ ├── partials │ │ │ │ └── modal.html │ │ │ ├── services │ │ │ │ ├── authService.js │ │ │ │ ├── config.js │ │ │ │ ├── customersBreezeService.js │ │ │ │ ├── customersService.js │ │ │ │ ├── dataService.js │ │ │ │ ├── httpInterceptors.js │ │ │ │ └── modalService.js │ │ │ └── views │ │ │ │ ├── about.html │ │ │ │ ├── customers │ │ │ │ ├── customerEdit.html │ │ │ │ ├── customerOrders.html │ │ │ │ └── customers.html │ │ │ │ ├── login.html │ │ │ │ └── orders │ │ │ │ ├── orders.html │ │ │ │ └── ordersTable.html │ │ └── wc.directives │ │ │ └── directives │ │ │ ├── lazyLoader.js │ │ │ ├── menuHighlighter.js │ │ │ └── wcOverlay.js │ ├── fonts │ │ ├── glyphicons-halflings-regular.eot │ │ ├── glyphicons-halflings-regular.svg │ │ ├── glyphicons-halflings-regular.ttf │ │ └── glyphicons-halflings-regular.woff │ ├── gulpfile.js │ ├── index.html │ ├── package.json │ ├── packages.config │ ├── server │ │ ├── accessDB.js │ │ ├── initMongoDB.bat │ │ ├── initMongoDB.sh │ │ ├── initMongoData.js │ │ ├── lib │ │ │ └── protectJSON.js │ │ ├── models │ │ │ ├── customer.js │ │ │ └── state.js │ │ ├── routes │ │ │ ├── api.js │ │ │ └── index.js │ │ ├── server.js │ │ └── views │ │ │ └── index.jade │ └── test │ │ ├── helpers │ │ └── serviceFactories.js │ │ ├── karma.conf.js │ │ ├── lib │ │ ├── angular-animate.js │ │ ├── angular-mocks.js │ │ ├── angular-route.js │ │ ├── angular.js │ │ ├── breeze.angular.js │ │ └── breeze.min.js │ │ └── unit │ │ ├── customersControllerSpec.js │ │ ├── customersServiceSpec.js │ │ ├── dataServiceSpec.js │ │ ├── modalServiceSpec.js │ │ ├── wcOverlaySpec.js │ │ └── wcUniqueSpec.js ├── LICENSE.txt └── readme.md ├── copyFolders.js ├── package.json └── readme.md /.gitignore: -------------------------------------------------------------------------------- 1 | bin 2 | obj 3 | *.suo 4 | packages 5 | *.mdf 6 | *.ldf 7 | node_modules 8 | .ds_store 9 | npm-debug.log 10 | -------------------------------------------------------------------------------- /Labs/Creating Application Factories-Services/End/Readme.txt: -------------------------------------------------------------------------------- 1 | See the Src folder for the solution files -------------------------------------------------------------------------------- /Labs/Creating Application Factories-Services/Files/CustomerManager/app/customersApp/app.js: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /Labs/Creating Application Factories-Services/Files/CustomerManager/app/customersApp/services/authService.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 3 | var injectParams = ['$http', '$rootScope']; 4 | 5 | var authFactory = function () { 6 | var serviceBase = '/api/dataservice/', 7 | factory = { 8 | loginPath: '/login', 9 | user: { 10 | isAuthenticated: false, 11 | roles: null 12 | } 13 | }; 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | return factory; 22 | }; 23 | 24 | authFactory.$inject = injectParams; 25 | 26 | angular.module('customersApp').factory('authService', authFactory); 27 | 28 | }()); 29 | 30 | -------------------------------------------------------------------------------- /Labs/Creating Application Factories-Services/Files/CustomerManager/app/customersApp/services/config.js: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /Labs/Creating Application Factories-Services/Files/CustomerManager/app/customersApp/services/dataService.js: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /Labs/Creating Custom Directives/End/Readme.txt: -------------------------------------------------------------------------------- 1 | See the Src folder for the solution files -------------------------------------------------------------------------------- /Labs/Creating Custom Directives/End/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |

Creating Custom Directives

5 |
6 |

myShared

7 | 8 | 9 |

myIsolate

10 | 11 | 12 |
13 | 14 | 15 | 54 | 55 | -------------------------------------------------------------------------------- /Labs/Creating Custom Directives/Files/CustomerManager/app/customersApp/directives/wcUnique.js: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /Labs/Creating a Module Factory Controller and View/Begin/app/views/customers.html: -------------------------------------------------------------------------------- 1 |
2 | Search: 3 |
4 |

Customers:

5 | 6 | 7 | 8 | 9 |
10 |
-------------------------------------------------------------------------------- /Labs/Creating a Module Factory Controller and View/Begin/app/views/orders.html: -------------------------------------------------------------------------------- 1 |

Orders

2 | Customer ID: {{ customerId }} 3 |
4 |
5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
Baseball$9.99
Bat$19.99
15 | 16 |
17 | 18 | Customers -------------------------------------------------------------------------------- /Labs/Creating a Module Factory Controller and View/Begin/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Getting Started with AngularJS 5 | 6 | 7 | 8 |

Getting Started with AngularJS

9 | 10 |
11 | 12 |      13 |      14 |      15 | 23 | 24 | -------------------------------------------------------------------------------- /Labs/Creating a Module Factory Controller and View/Begin/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "AngularJSApp", 3 | "version": "1.0.0", 4 | "description": "Sample App", 5 | "author": "Dan Wahlin", 6 | "engines": { 7 | "node": ">=0.10.28" 8 | }, 9 | "dependencies": { 10 | "express": "^4.9.6" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Labs/Creating a Module Factory Controller and View/Begin/server.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var app = express(); 3 | 4 | app.use(express.static(__dirname)); 5 | 6 | app.listen(8000); 7 | console.log('Listening on port 8000'); -------------------------------------------------------------------------------- /Labs/Creating a Module Factory Controller and View/Begin/snippets.js: -------------------------------------------------------------------------------- 1 | var app = angular.module('demoApp',['ngRoute', 'ngAnimate']); 2 | 3 | app.config(function($routeProvider) { 4 | $routeProvider.when('/', 5 | { 6 | controller: 'CustomersController', 7 | templateUrl: 'app/views/customers.html' 8 | }) 9 | .when('/orders/:customerId', 10 | { 11 | controller: 'OrdersController', 12 | templateUrl: 'app/views/orders.html' 13 | }) 14 | }); 15 | 16 | app.controller('CustomersController', function($scope, customersFactory) { 17 | $scope.customers = null; 18 | 19 | function init() { 20 | $scope.customers = customersFactory.getCustomers(); 21 | } 22 | 23 | init(); 24 | }); 25 | 26 | app.controller('OrdersController', function($scope, $routeParams) { 27 | $scope.customerId = $routeParams.customerId; 28 | }); 29 | 30 | app.factory('customersFactory', function() { 31 | var customers = [ 32 | {id: 1, name:"Ted", total: 5.996}, 33 | {id: 2, name:"Michelle", total: 10.994}, 34 | {id: 3, name:"Zed", total: 10.99}, 35 | {id: 4, name:"Tina", total: 15.994} 36 | ]; 37 | var factory = {}; 38 | factory.getCustomers = function() { 39 | return customers; 40 | }; 41 | return factory; 42 | }); -------------------------------------------------------------------------------- /Labs/Creating a Module Factory Controller and View/End/app/views/customers.html: -------------------------------------------------------------------------------- 1 |
2 | Search: 3 |
4 |

Customers:

5 | 6 | 7 | 8 | 9 | 10 |
{{ cust.name }}{{ cust.total | currency }}
11 |
-------------------------------------------------------------------------------- /Labs/Creating a Module Factory Controller and View/End/app/views/orders.html: -------------------------------------------------------------------------------- 1 |

Orders

2 | Customer ID: {{ customerId }} 3 |
4 |
5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
Baseball$9.99
Bat$19.99
15 | 16 |
17 | 18 | Customers -------------------------------------------------------------------------------- /Labs/Creating a Module Factory Controller and View/End/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Getting Started with AngularJS 5 | 6 | 7 | 8 |

Getting Started with AngularJS

9 | 10 |
11 | 12 |      13 |      14 |      15 | 60 | 61 | -------------------------------------------------------------------------------- /Labs/Creating a Module Factory Controller and View/End/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "AngularJSApp", 3 | "version": "1.0.0", 4 | "description": "Sample App", 5 | "author": "Dan Wahlin", 6 | "engines": { 7 | "node": ">=0.10.28" 8 | }, 9 | "dependencies": { 10 | "express": "^4.9.6" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Labs/Creating a Module Factory Controller and View/End/server.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var app = express(); 3 | 4 | app.use(express.static(__dirname)); 5 | 6 | app.listen(8000); 7 | console.log('Listening on port 8000'); -------------------------------------------------------------------------------- /Labs/Creating a Module Factory Controller and View/End/snippets.js: -------------------------------------------------------------------------------- 1 | var app = angular.module('demoApp',['ngRoute', 'ngAnimate']); 2 | 3 | app.config(function($routeProvider) { 4 | $routeProvider.when('/', 5 | { 6 | controller: 'CustomersController', 7 | templateUrl: 'app/views/customers.html' 8 | }) 9 | .when('/orders/:customerId', 10 | { 11 | controller: 'OrdersController', 12 | templateUrl: 'app/views/orders.html' 13 | }) 14 | }); 15 | 16 | app.controller('CustomersController', function($scope, customersFactory) { 17 | $scope.customers = null; 18 | 19 | function init() { 20 | $scope.customers = customersFactory.getCustomers(); 21 | } 22 | 23 | init(); 24 | }); 25 | 26 | app.controller('OrdersController', function($scope, $routeParams) { 27 | $scope.customerId = $routeParams.customerId; 28 | }); 29 | 30 | app.factory('customersFactory', function() { 31 | var customers = [ 32 | {id: 1, name:"Ted", total: 5.996}, 33 | {id: 2, name:"Michelle", total: 10.994}, 34 | {id: 3, name:"Zed", total: 10.99}, 35 | {id: 4, name:"Tina", total: 15.994} 36 | ]; 37 | var factory = {}; 38 | factory.getCustomers = function() { 39 | return customers; 40 | }; 41 | return factory; 42 | }); -------------------------------------------------------------------------------- /Labs/Creating the CustomersController and View/End/Readme.txt: -------------------------------------------------------------------------------- 1 | See the Src folder for the solution files -------------------------------------------------------------------------------- /Labs/Creating the CustomersController and View/Files/CustomerManager/app/customersApp/controllers/customers/customersController.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 3 | var injectParams = ['$location', '$filter', '$window', 4 | '$timeout', 'authService', 'dataService', 'modalService']; 5 | 6 | var CustomersController = function ($location, $filter, $window, 7 | $timeout, authService, dataService, modalService) { 8 | 9 | var vm = this; 10 | 11 | 12 | 13 | vm.deleteCustomer = function (id) { 14 | //Check auth 15 | 16 | 17 | 18 | var cust = getCustomerById(id); 19 | var custName = cust.firstName + ' ' + cust.lastName; 20 | 21 | var modalOptions = { 22 | closeButtonText: 'Cancel', 23 | actionButtonText: 'Delete Customer', 24 | headerText: 'Delete ' + custName + '?', 25 | bodyText: 'Are you sure you want to delete this customer?' 26 | }; 27 | 28 | modalService.showModal({}, modalOptions).then(function (result) { 29 | if (result === 'ok') { 30 | 31 | } 32 | }); 33 | }; 34 | 35 | vm.navigate = function (url) { 36 | $location.path(url); 37 | }; 38 | 39 | vm.setOrder = function (orderby) { 40 | if (orderby === vm.orderby) { 41 | vm.reverse = !vm.reverse; 42 | } 43 | vm.orderby = orderby; 44 | }; 45 | 46 | function getCustomerById(id) { 47 | for (var i = 0; i < vm.customers.length; i++) { 48 | var cust = vm.customers[i]; 49 | if (cust.id === id) { 50 | return cust; 51 | } 52 | } 53 | return null; 54 | } 55 | 56 | init(); 57 | }; 58 | 59 | CustomersController.$inject = injectParams; 60 | 61 | angular.module('customersApp').controller('CustomersController', CustomersController); 62 | 63 | }()); 64 | -------------------------------------------------------------------------------- /Labs/Creating the LoginController and View/End/Readme.txt: -------------------------------------------------------------------------------- 1 | See the Src folder for the solution files -------------------------------------------------------------------------------- /Labs/Creating the LoginController and View/Files/CustomerManager/app/customersApp/controllers/loginController.js: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /Labs/Creating the LoginController and View/Files/CustomerManager/app/customersApp/views/login.html: -------------------------------------------------------------------------------- 1 | 
2 |
3 |
4 |

Login

5 |
6 |
7 | 41 |
42 |
43 |
44 | 45 | -------------------------------------------------------------------------------- /Labs/Creating the NavbarController and View/End/Readme.txt: -------------------------------------------------------------------------------- 1 | See the Src folder for the solution files -------------------------------------------------------------------------------- /Labs/Creating the NavbarController and View/Files/CustomerManager/app/customersApp/controllers/navbarController.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 3 | var injectParams = ['$scope', '$location', 'config', 'authService']; 4 | 5 | var NavbarController = function ($scope, $location, config, authService) { 6 | 7 | 8 | 9 | 10 | 11 | 12 | }; 13 | 14 | NavbarController.$inject = injectParams; 15 | 16 | angular.module('customersApp').controller('NavbarController', NavbarController); 17 | 18 | }()); 19 | -------------------------------------------------------------------------------- /Labs/Defining Application Routes/End/Readme.txt: -------------------------------------------------------------------------------- 1 | See the Src folder for the solution files -------------------------------------------------------------------------------- /Labs/Defining Application Routes/Files/CustomerManager/app/customersApp/app.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 3 | var app = angular.module('customersApp', 4 | ['ngRoute', 'ngAnimate', 'wc.directives', 'ui.bootstrap', 'breeze.angular']); 5 | 6 | 7 | 8 | }()); 9 | 10 | -------------------------------------------------------------------------------- /Labs/Unit Testing AngularJS Components/Begin/app/app.js: -------------------------------------------------------------------------------- 1 | var reminderApp=angular.module('reminderApp',[]); 2 | 3 | reminderApp.controller('ReminderController', function($scope,reminderFactory) { 4 | 5 | $scope.reminders = reminderFactory.get(); 6 | 7 | $scope.$on("newReminder", function(event) { 8 | $scope.reminders = reminderFactory.get(); 9 | }); 10 | 11 | 12 | $scope.createReminder=function() { 13 | reminderFactory.put($scope.reminder); 14 | $scope.reminder = ""; 15 | } 16 | }); 17 | 18 | reminderApp.factory('reminderFactory',function($rootScope){ 19 | return { 20 | 21 | get:function(){ 22 | var reminders=[]; 23 | var keys=Object.keys(localStorage); 24 | for(var i=0;i li { 19 | display: inline; 20 | } 21 | 22 | .menu > li:before { 23 | content: "|"; 24 | padding-right: 0.3em; 25 | } 26 | 27 | .menu > li:nth-child(1):before { 28 | content: ""; 29 | padding: 0; 30 | } 31 | -------------------------------------------------------------------------------- /Labs/Unit Testing AngularJS Components/Begin/app/lib/jasmine/MIT.LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2008-2011 Pivotal Labs 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /Labs/Unit Testing AngularJS Components/Begin/app/lib/jasmine/jasmine_favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DanWahlin/AngularJSEndToEndCourseCode/12cf7f9f1213e481fa1c140f761e7e766a555845/Labs/Unit Testing AngularJS Components/Begin/app/lib/jasmine/jasmine_favicon.png -------------------------------------------------------------------------------- /Labs/Unit Testing AngularJS Components/Begin/app/reminders.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 20 | 21 | Angular Reminder App 22 | 23 | 24 |
25 |
26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 |
36 |
37 | 38 | 39 |
    40 |
  • 41 | {{reminder}} 42 |
  • 43 |
44 |
45 | 46 |
47 |
48 | 49 | -------------------------------------------------------------------------------- /Labs/Unit Testing AngularJS Components/Begin/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "unit-testing", 3 | "description": "Unit Testing Demos", 4 | "devDependencies": { 5 | "phantomjs-prebuilt": "^2.1.14", 6 | "karma": "^1.5.0", 7 | "karma-jasmine": "^1.1.0", 8 | "karma-ng-scenario": "^1.0.0", 9 | "karma-chrome-launcher": "^2.0.0", 10 | "jasmine": "^2.5.3", 11 | "express": "^4.15.2" 12 | } 13 | } -------------------------------------------------------------------------------- /Labs/Unit Testing AngularJS Components/Begin/server.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var app = express(); 3 | 4 | app.use(express.static(__dirname)); 5 | 6 | app.listen(8000); 7 | console.log('Listening on port 8000'); -------------------------------------------------------------------------------- /Labs/Unit Testing AngularJS Components/Begin/test/unit/servicesSpec.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('reminderFactory tests', function (){ 4 | var factory; 5 | 6 | //excuted before each "it" is run. 7 | beforeEach(function (){ 8 | 9 | module('reminderApp'); 10 | 11 | //inject factory for testing 12 | inject(function(reminderFactory) { 13 | factory = reminderFactory; 14 | }); 15 | 16 | var store = {reminder1:'reminder1',reminder2:'reminder2',reminder3:'reminder3'}; 17 | 18 | spyOn(localStorage, 'getItem').and.callFake(function (key) { 19 | return store[key]; 20 | }); 21 | 22 | spyOn(localStorage, 'setItem').and.callFake(function (key, value) { 23 | return store[key] = value + ''; 24 | }); 25 | 26 | spyOn(localStorage, 'clear').and.callFake(function () { 27 | store = {}; 28 | }); 29 | 30 | spyOn(Object, 'keys').and.callFake(function (key) { 31 | var keys=[]; 32 | for(var key in store) 33 | keys.push(key); 34 | return keys; 35 | }); 36 | 37 | }); 38 | 39 | 40 | 41 | 42 | 43 | }); 44 | -------------------------------------------------------------------------------- /Labs/Unit Testing AngularJS Components/End/app/app.js: -------------------------------------------------------------------------------- 1 | var reminderApp=angular.module('reminderApp',[]); 2 | 3 | reminderApp.controller('ReminderController', function($scope,reminderFactory) { 4 | 5 | $scope.reminders = reminderFactory.get(); 6 | 7 | $scope.$on("newReminder", function(event) { 8 | $scope.reminders = reminderFactory.get(); 9 | }); 10 | 11 | 12 | $scope.createReminder=function() { 13 | reminderFactory.put($scope.reminder); 14 | $scope.reminder = ""; 15 | } 16 | }); 17 | 18 | reminderApp.factory('reminderFactory',function($rootScope){ 19 | return { 20 | 21 | get:function(){ 22 | var reminders=[]; 23 | var keys=Object.keys(localStorage); 24 | for(var i=0;i li { 19 | display: inline; 20 | } 21 | 22 | .menu > li:before { 23 | content: "|"; 24 | padding-right: 0.3em; 25 | } 26 | 27 | .menu > li:nth-child(1):before { 28 | content: ""; 29 | padding: 0; 30 | } 31 | -------------------------------------------------------------------------------- /Labs/Unit Testing AngularJS Components/End/app/lib/jasmine/MIT.LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2008-2011 Pivotal Labs 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /Labs/Unit Testing AngularJS Components/End/app/lib/jasmine/jasmine_favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DanWahlin/AngularJSEndToEndCourseCode/12cf7f9f1213e481fa1c140f761e7e766a555845/Labs/Unit Testing AngularJS Components/End/app/lib/jasmine/jasmine_favicon.png -------------------------------------------------------------------------------- /Labs/Unit Testing AngularJS Components/End/app/reminders.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 20 | 21 | Angular Reminder App 22 | 23 | 24 |
25 |
26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 |
36 |
37 | 38 | 39 |
    40 |
  • 41 | {{reminder}} 42 |
  • 43 |
44 |
45 | 46 |
47 |
48 | 49 | -------------------------------------------------------------------------------- /Labs/Unit Testing AngularJS Components/End/karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration 2 | // Generated on Sat Mar 22 2014 20:03:21 GMT-0700 (US Mountain Standard Time) 3 | 4 | module.exports = function(config) { 5 | config.set({ 6 | 7 | // base path that will be used to resolve all patterns (eg. files, exclude) 8 | basePath: '', 9 | 10 | 11 | // frameworks to use 12 | // available frameworks: https://npmjs.org/browse/keyword/karma-adapter 13 | frameworks: ['jasmine'], 14 | 15 | 16 | // list of files / patterns to load in the browser 17 | files: [ 18 | 'app/lib/angular.js', 19 | 'app/lib/angular-*.js', 20 | 'app/*.js', 21 | 'test/unit/*.js' 22 | ], 23 | 24 | 25 | // list of files to exclude 26 | exclude: [ 27 | 28 | ], 29 | 30 | 31 | // preprocess matching files before serving them to the browser 32 | // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor 33 | preprocessors: { 34 | 35 | }, 36 | 37 | 38 | // test results reporter to use 39 | // possible values: 'dots', 'progress' 40 | // available reporters: https://npmjs.org/browse/keyword/karma-reporter 41 | reporters: ['progress'], 42 | 43 | 44 | // web server port 45 | port: 9876, 46 | 47 | 48 | // enable / disable colors in the output (reporters and logs) 49 | colors: true, 50 | 51 | 52 | // level of logging 53 | // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG 54 | logLevel: config.LOG_INFO, 55 | 56 | 57 | // enable / disable watching file and executing tests whenever any file changes 58 | autoWatch: true, 59 | 60 | 61 | // start these browsers 62 | // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher 63 | browsers: ['Chrome'], 64 | 65 | 66 | // Continuous Integration mode 67 | // if true, Karma captures browsers, runs the tests and exits 68 | singleRun: false 69 | }); 70 | }; 71 | -------------------------------------------------------------------------------- /Labs/Unit Testing AngularJS Components/End/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "unit-testing", 3 | "description": "Unit Testing Demos", 4 | "devDependencies": { 5 | "phantomjs-prebuilt": "^2.1.14", 6 | "karma": "^1.5.0", 7 | "karma-jasmine": "^1.1.0", 8 | "karma-ng-scenario": "^1.0.0", 9 | "karma-chrome-launcher": "^2.0.0", 10 | "jasmine": "^2.5.3", 11 | "express": "^4.15.2" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Labs/Unit Testing AngularJS Components/End/server.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var app = express(); 3 | 4 | app.use(express.static(__dirname)); 5 | 6 | app.listen(8000); 7 | console.log('Listening on port 8000'); -------------------------------------------------------------------------------- /Labs/Unit Testing AngularJS Components/End/test/unit/controllersSpec.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('ReminderController Test', function() { 4 | var scope, controller; 5 | var mockFactory = { 6 | reminders:['reminder1','reminder2'], 7 | get: function (){ 8 | return this.reminders; 9 | }, 10 | put:function(content){ 11 | this.reminders.push(content); 12 | } 13 | }; 14 | 15 | beforeEach(function() { 16 | module('reminderApp'); 17 | 18 | inject(function($rootScope, $controller) { 19 | scope = $rootScope.$new(); 20 | controller = $controller("ReminderController", 21 | {$scope: scope, reminderFactory:mockFactory }); 22 | }); 23 | }); 24 | it('should return reminders array with 2 elements, add one,' + 25 | ' and return 3', function() { 26 | expect(scope.reminders.length).toBe(2); 27 | scope.reminder = "reminder3"; 28 | scope.createReminder(); 29 | expect(scope.reminders.length).toBe(3); 30 | }); 31 | 32 | 33 | 34 | }); 35 | -------------------------------------------------------------------------------- /Labs/Unit Testing AngularJS Components/End/test/unit/servicesSpec.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('reminderFactory tests', function (){ 4 | var factory; 5 | 6 | //excuted before each "it" is run. 7 | beforeEach(function (){ 8 | 9 | module('reminderApp'); 10 | 11 | //inject factory for testing 12 | inject(function(reminderFactory) { 13 | factory = reminderFactory; 14 | }); 15 | 16 | var store = {reminder1:'reminder1',reminder2:'reminder2',reminder3:'reminder3'}; 17 | 18 | spyOn(localStorage, 'getItem').and.callFake(function (key) { 19 | return store[key]; 20 | }); 21 | 22 | spyOn(localStorage, 'setItem').and.callFake(function (key, value) { 23 | return store[key] = value + ''; 24 | }); 25 | 26 | spyOn(localStorage, 'clear').and.callFake(function () { 27 | store = {}; 28 | }); 29 | 30 | spyOn(Object, 'keys').and.callFake(function (key) { 31 | var keys=[]; 32 | for(var key in store) 33 | keys.push(key); 34 | return keys; 35 | }); 36 | 37 | }); 38 | 39 | it('should have get and put functions', function () { 40 | expect(angular.isFunction(factory.get)).toBe(true); 41 | expect(angular.isFunction(factory.put)).toBe(true); 42 | }); 43 | 44 | it('should return 3 reminders initially', function () { 45 | var result = factory.get(); 46 | expect(result.length).toBe(3); 47 | }); 48 | 49 | it('should return 4 reminders after adding one more', function () { 50 | factory.put('reminder4'); 51 | var result = factory.get(); 52 | expect(result.length).toBe(4); 53 | }); 54 | 55 | 56 | 57 | }); 58 | -------------------------------------------------------------------------------- /Labs/Working with Controllers and Watches/Begin/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |

Using Watches in Controllers

5 |
6 | 7 | 8 |
9 |

Actions

10 | 11 | 12 | 13 |

14 |    15 |    16 |    17 |
18 | 19 | 20 | 24 | 25 | -------------------------------------------------------------------------------- /Samples/AngularJSStarterDemo/app/views/customers.html: -------------------------------------------------------------------------------- 1 |
2 | Search: 3 |
4 |

Customers:

5 | 6 | 7 | 8 | 9 | 10 |
{{ cust.name }}{{ cust.total | currency }}
11 |
-------------------------------------------------------------------------------- /Samples/AngularJSStarterDemo/app/views/orders.html: -------------------------------------------------------------------------------- 1 |

Orders

2 | 3 | CustomerID: {{ customerId }} 4 |
5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
Baseball$9.99
Bat$19.99
15 | 16 |
17 | 18 | Customers -------------------------------------------------------------------------------- /Samples/AngularJSStarterDemo/customers.json: -------------------------------------------------------------------------------- 1 | [ 2 | {"id": 1, "name":"Ted", "total": 5.996}, 3 | {"id": 2, "name":"Michelle", "total": 10.994}, 4 | {"id": 3, "name":"Zed", "total": 10.99}, 5 | {"id": 4, "name":"Tina", "total": 15.994} 6 | ] -------------------------------------------------------------------------------- /Samples/AngularJSStarterDemo/index.html: -------------------------------------------------------------------------------- 1 | 14 | 15 | 16 | 17 | Angular App 18 | 19 | 20 | 21 |

AngularJS in 20-ish Minutes

22 | 23 |
24 | 25 | 26 | 27 | 28 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /Samples/AngularJSStarterDemo/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angularjs-app", 3 | "version": "1.0.0", 4 | "description": "Sample App", 5 | "author": "Dan Wahlin", 6 | "dependencies": { 7 | "express": "^4.15.2" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Samples/AngularJSStarterDemo/server.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var app = express(); 3 | 4 | app.use(express.static(__dirname)); 5 | 6 | app.listen(8000); 7 | console.log('Listening on port 8000'); -------------------------------------------------------------------------------- /Samples/AngularJSStarterDemo/snippets.js: -------------------------------------------------------------------------------- 1 | $scope.customers = [ 2 | {"id": 1, "name":"Ted", "total": 5.996}, 3 | {"id": 2, "name":"Michelle", "total": 10.994}, 4 | {"id": 3, "name":"Zed", "total": 10.99}, 5 | {"id": 4, "name":"Tina", "total": 15.994} 6 | ]; 7 | 8 | 9 | app.config(function($routeProvider) { 10 | $routeProvider.when('/', 11 | { 12 | controller: 'CustomersController', 13 | templateUrl: 'app/views/customers.html' 14 | }) 15 | .when('/orders', 16 | { 17 | controller: 'OrdersController', 18 | templateUrl: 'app/views/orders.html' 19 | }) 20 | }); 21 | 22 | 23 | app.factory('customersFactory', function($http) { 24 | var factory = {}; 25 | factory.getCustomers = function() { 26 | return $http.get('/customers.json'); 27 | }; 28 | return factory; 29 | }); -------------------------------------------------------------------------------- /Samples/BroadcastAndEmit/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Broadcast and Emit 6 | 7 | 8 | 9 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | Root scope MyEvent count: {{count}} 26 |
    27 |
  • 28 | 29 | 30 |

    31 | Middle scope MyEvent count: {{count}} 32 |
      33 |
    • 34 | Leaf scope MyEvent count: {{count}} 35 |
    • 36 |
    37 |
  • 38 |
39 |
40 | 41 | 42 | -------------------------------------------------------------------------------- /Samples/Directives/compile.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Using Compile in a Directive 5 | 6 | 7 |
9 | 10 |

Using Compile in a Directive

11 | Open the console to see the output of compile, pre-link, and post-link. 12 |
13 |
14 |
15 |
16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /Samples/Directives/component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Component Demo 5 | 6 | 7 | 8 |
10 | 11 |

Using a Component

12 | 13 |

Parent Customers

14 |
    15 |
  • {{cust.name}}
  • 16 |
17 |
18 |

Customer Component

19 | Note that changes in component update the parent...don't do this! 20 |

21 | 24 | 25 | 26 |

Customer Component (no changes in component)

27 | 29 | 30 | 31 |
32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /Samples/Directives/controller.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Using a Controller in a Directive 5 | 6 | 7 | 8 |
10 | 11 | Parent Scope Customers: 12 |

13 |
  • {{ cust.name }}
14 | 15 |

Directive with Controller

16 | Attribute:
17 |

18 | Element:
19 | 20 |
21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Samples/Directives/controllerAs.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Using controllerAs in a Directive 5 | 6 | 7 | 8 |
10 | 11 | Parent Scope Customers: 12 |

13 |
  • {{ cust.name }}
14 | 15 |

Directive with Controller

16 | Attribute:
17 |

18 | Element:
19 | 20 |
21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /Samples/Directives/controllerNotUsed.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Directive without a Controller 5 | 6 | 7 | 8 |
10 | 11 | Parent Scope Customers: 12 |

13 |
  • {{ cust.name }}
14 | 15 |

Directive without a Controller (naive example)

16 | Attribute:
17 |

18 | Element:
19 | 20 |
21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Samples/Directives/controllerPassingParameter1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Controller Passing a Parameter 5 | 6 | 7 | 8 |
10 | 11 | Parent Scope Customers: 12 |

13 |
  • {{ cust.name }}
14 | 15 |

Directive with Controller

16 | Attribute:
17 |

18 | Element:
19 | 20 |
21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /Samples/Directives/controllerPassingParameter2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Controller Passing a Parameter 5 | 6 | 7 | 8 |
10 | 11 | Parent Scope Customers: 12 |

13 |
  • {{ cust.name }}
14 | 15 |

Directive with Controller

16 | Attribute:
17 |

18 | Element:
19 | 20 |
21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Samples/Directives/isolateScope.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Isolate Scope Directive 5 | 6 | 7 | 8 |
10 | 11 |

Isolate Scope Directive

12 | Directive output (no output since parent scope isn't shared) 13 |
14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /Samples/Directives/isolateScopeWithModel.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Isolate Scope Directive 5 | 6 | 7 | 8 |
10 | 11 |

Directive with Isolate Scope and Model (uses =)

12 | This relies on the "=" isolate scope property to pass data into the directive. 13 |
14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /Samples/Directives/isolateScopeWithModelAndElement.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Isolate Scope Directive 5 | 6 | 7 | 8 |
10 | 11 |

Directive with isolate Scope and Model (uses = and restrict)

12 | 13 | Attribute:
14 | 15 |

16 | 17 | Element:
18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /Samples/Directives/isolateScopeWithModelAndEvent.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Isolate Scope Directive 5 | 6 | 7 | 8 |
10 | 11 |

Directive with isolate Scope, Model and Event

12 | 13 | Parent scope values: {{ customer.name }}, {{ customer.street }} 14 | 15 |

16 | 17 | This will call the controller's changeData() method from the directive. 18 | 19 |

20 | 21 | Attribute: 22 |
23 | 24 |

25 | 26 | Element:
27 | 28 |
29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /Samples/Directives/isolateScopeWithModelEventAndArray.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Isolate Scope Directive 5 | 6 | 7 | 8 |
10 | 11 |

Directive with isolate Scope, Model, Event, and Array

12 | 13 | Parent Scope Customers: 14 |

15 |
  • {{ cust.name }}
16 |
17 | 18 | Attribute:
19 |

20 | Element:
21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /Samples/Directives/isolateScopeWithString.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Isolate Scope Directive 5 | 6 | 7 | 8 |
10 | 11 |

Directive with Isolate Scope and String Passed In (uses @)

12 |
13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /Samples/Directives/js/compileDirective.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | var app = angular.module('directivesModule'); 4 | 5 | app.directive('compileDirective', function () { 6 | return { 7 | restrict: 'A', 8 | compile: function(tElem, tAttrs) { 9 | console.log('Compile output: ' + tElem.html()); 10 | console.log(''); 11 | return { 12 | pre: function(scope, elem, attrs){ 13 | console.log('\nPre link output: ' + elem.html()); 14 | console.log(''); 15 | }, 16 | post: function(scope, elem, attrs){ 17 | console.log('\nPost link output: ' + elem.html()); 18 | console.log(''); 19 | } 20 | } 21 | } 22 | }; 23 | }); 24 | 25 | }()); -------------------------------------------------------------------------------- /Samples/Directives/js/component.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | function CustomerDetailController() { 4 | var ctrl = this; 5 | 6 | ctrl.$onInit = function() { 7 | console.log('onInit called in component'); 8 | console.log(ctrl.customer); 9 | }; 10 | 11 | //Could add additional functionality here (functions to call for example) 12 | } 13 | 14 | angular.module('directivesModule') 15 | .component('customerDetail', { 16 | 17 | template: ` 18 |
19 | Name: 20 | 21 |
22 | `, 23 | controller: CustomerDetailController, 24 | bindings: { 25 | customer: '<', //One-way binding (but be careful not to change data in comnponent) 26 | changeCustomer: '&' //Expression/function binding 27 | } 28 | 29 | }); 30 | 31 | angular.module('directivesModule') 32 | .component('customerDetailNoChanges', { 33 | 34 | template: '
Name: {{ $ctrl.customer.name }}
', 35 | controller: CustomerDetailController, 36 | bindings: { 37 | customer: '<' 38 | } 39 | 40 | }); 41 | 42 | }()); -------------------------------------------------------------------------------- /Samples/Directives/js/controllerAsDirective.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | var app = angular.module('directivesModule'); 4 | 5 | app.directive('controllerAs', function () { 6 | 7 | var controller = function () { 8 | 9 | var vm = this; 10 | 11 | function init() { 12 | //Create a copy of the original data that’s passed in 13 | vm.items = angular.copy(vm.datasource); 14 | } 15 | 16 | init(); 17 | 18 | vm.addItem = function () { 19 | vm.add(); 20 | 21 | //Add new customer to directive scope 22 | vm.items.push({ 23 | name: 'New Directive Controller Item' 24 | }); 25 | }; 26 | }; 27 | 28 | var template = '' + 29 | ''; 30 | 31 | return { 32 | restrict: 'EA', //Default for 1.3+ 33 | scope: { 34 | datasource: '=', 35 | add: '&', 36 | }, 37 | controller: controller, 38 | controllerAs: 'vm', 39 | bindToController: true, //required in 1.3+ with controllerAs 40 | template: template 41 | }; 42 | }); 43 | 44 | }()); -------------------------------------------------------------------------------- /Samples/Directives/js/controllerDirective.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | var app = angular.module('directivesModule'); 4 | 5 | app.directive('controller', function () { 6 | 7 | var controller = ['$scope', function ($scope) { 8 | 9 | function init() { 10 | //Create a copy of the original data that’s passed in 11 | $scope.items = angular.copy($scope.datasource); 12 | } 13 | 14 | init(); 15 | 16 | $scope.addItem = function () { 17 | $scope.add(); 18 | 19 | //Add new customer to directive scope 20 | $scope.items.push({ 21 | name: 'New Directive Controller Item' 22 | }); 23 | }; 24 | }], 25 | 26 | template = ''; 28 | 29 | return { 30 | restrict: 'EA', //Default in 1.3+ 31 | scope: { 32 | datasource: '=', 33 | add: '&', 34 | }, 35 | controller: controller, 36 | template: template 37 | }; 38 | }); 39 | 40 | }()); -------------------------------------------------------------------------------- /Samples/Directives/js/controllerNotUsed.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | var app = angular.module('directivesModule'); 4 | 5 | app.directive('controllerNotUsed', function () { 6 | 7 | var link = function (scope, element, attrs) { 8 | 9 | //Create a copy of the original data that’s passed in 10 | var items = angular.copy(scope.datasource); 11 | 12 | function init() { 13 | var html = '
'; 14 | element.html(html); 15 | 16 | element.on('click', function(event) { 17 | if (event.srcElement.id === 'addItem') { 18 | addItem(); 19 | event.preventDefault(); 20 | } 21 | }); 22 | } 23 | 24 | function addItem() { 25 | //Call external function passed in with & 26 | scope.add(); 27 | 28 | //Add new customer to the local collection 29 | items.push({ 30 | name: 'New Directive Customer' 31 | }); 32 | 33 | render(); 34 | } 35 | 36 | function render() { 37 | var html = ''; 42 | 43 | element.find('div').html(html); 44 | } 45 | 46 | init(); 47 | render(); 48 | }; 49 | 50 | 51 | return { 52 | restrict: 'EA', 53 | scope: { 54 | datasource: '=', 55 | add: '&', 56 | }, 57 | link: link 58 | }; 59 | }); 60 | 61 | }()); -------------------------------------------------------------------------------- /Samples/Directives/js/controllerPassingParameter1Directive.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | var app = angular.module('directivesModule'); 4 | 5 | app.directive('controllerPassingParameter1', function () { 6 | var controller = function () { 7 | 8 | var vm = this; 9 | 10 | function init() { 11 | vm.items = angular.copy(vm.datasource); 12 | } 13 | init(); 14 | 15 | vm.addItem = function () { 16 | //Call external scope's function 17 | var name = 'New Customer Added by Directive'; 18 | vm.add({name: name}); 19 | 20 | //Add new item to directive scope 21 | vm.items.push({ 22 | name: name 23 | }); 24 | }; 25 | }, 26 | 27 | template = ''; 29 | 30 | return { 31 | restrict: 'EA', 32 | scope: { 33 | datasource: '=', 34 | add: '&', 35 | }, 36 | controller: controller, 37 | controllerAs: 'vm', 38 | bindToController: true, 39 | template: template 40 | }; 41 | }); 42 | }()); -------------------------------------------------------------------------------- /Samples/Directives/js/controllerPassingParameter2Directive.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | var app = angular.module('directivesModule'); 4 | 5 | app.directive('controllerPassingParameter2', function () { 6 | var controller = function () { 7 | 8 | var vm = this; 9 | 10 | function init() { 11 | vm.items = angular.copy(vm.datasource); 12 | } 13 | init(); 14 | 15 | vm.addItem = function () { 16 | //Call external scope's function 17 | var name = 'New Customer Added by Directive'; 18 | vm.add()(name); 19 | 20 | //Add new item to directive scope 21 | vm.items.push({ 22 | name: name 23 | }); 24 | }; 25 | }, 26 | 27 | template = ''; 29 | 30 | return { 31 | restrict: 'EA', 32 | scope: { 33 | datasource: '=', 34 | add: '&', 35 | }, 36 | controller: controller, 37 | controllerAs: 'vm', 38 | bindToController: true, 39 | template: template 40 | }; 41 | }); 42 | }()); -------------------------------------------------------------------------------- /Samples/Directives/js/directivesController.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | var app = angular.module('directivesModule', []); 4 | 5 | var injectParams = ['$scope']; 6 | 7 | var CustomersController = function ($scope) { 8 | var counter = 0; 9 | $scope.tasks = [{ title: 'Task 1' }]; 10 | $scope.customer = { 11 | name: 'David', 12 | street: '1234 Anywhere St.' 13 | }; 14 | 15 | $scope.customers = [ 16 | { 17 | name: 'David', 18 | street: '1234 Anywhere St.', 19 | age: 25, 20 | url: 'index.html' 21 | }, 22 | { 23 | name: 'Tina', 24 | street: '1800 Crest St.', 25 | age: 35, 26 | url: 'index.html' 27 | }, 28 | { 29 | name: 'Michelle', 30 | street: '890 Main St.', 31 | age: 29, 32 | url: 'index.html' 33 | }, 34 | { 35 | name: 'John', 36 | street: '444 Cedar St.', 37 | age: 18, 38 | url: 'index.html' 39 | } 40 | ]; 41 | 42 | $scope.addCustomer = function (name) { 43 | console.log(name); 44 | counter++; 45 | $scope.customers.push({ 46 | name: (name) ? name : 'New Customer' + counter, 47 | street: counter + ' Cedar Point St.', 48 | age: counter 49 | }); 50 | }; 51 | 52 | $scope.changeData = function () { 53 | counter++; 54 | $scope.customer = { 55 | name: 'James', 56 | street: counter + ' Cedar Point St.' 57 | }; 58 | }; 59 | 60 | $scope.changeName = function(customer) { 61 | customer.name = 'foo'; 62 | }; 63 | }; 64 | 65 | CustomersController.$inject = injectParams; 66 | 67 | app.controller('CustomersController', CustomersController); 68 | 69 | }()); -------------------------------------------------------------------------------- /Samples/Directives/js/isolateScopeDirective.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | var app = angular.module('directivesModule'); 4 | 5 | app.directive('isolateScope', function () { 6 | return { 7 | scope: {}, 8 | template: 'Name: {{customer.name}} Street: {{customer.street}}' 9 | }; 10 | }); 11 | 12 | }()); -------------------------------------------------------------------------------- /Samples/Directives/js/isolateScopeWithModelAndElementDirective.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | var app = angular.module('directivesModule'); 4 | 5 | app.directive('isolateScopeWithModelAndElement', function () { 6 | return { 7 | restrict: 'EA', //Restrict to Element and Attribute 8 | scope: { 9 | datasource: '=' 10 | }, 11 | template: 'Name: {{datasource.name}} Street: {{datasource.street}}' 12 | }; 13 | }); 14 | 15 | }()); -------------------------------------------------------------------------------- /Samples/Directives/js/isolateScopeWithModelAndEventDirective.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | var app = angular.module('directivesModule'); 4 | 5 | app.directive('isolateScopeWithModelAndEvent', function () { 6 | return { 7 | restrict: 'EA', 8 | scope: { 9 | datasource: '=', 10 | click: '&' 11 | }, 12 | template: 'Name: {{datasource.name}} Street: {{datasource.street}} ' 13 | }; 14 | }); 15 | 16 | }()); -------------------------------------------------------------------------------- /Samples/Directives/js/isolateScopeWithModelDirective.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | var app = angular.module('directivesModule'); 4 | 5 | app.directive('isolateScopeWithModel', function () { 6 | return { 7 | scope: { 8 | datasource: '=' //Two-way data binding 9 | }, 10 | template: 'Name: {{datasource.name}} Street: {{datasource.street}}' 11 | }; 12 | }); 13 | 14 | }()); -------------------------------------------------------------------------------- /Samples/Directives/js/isolateScopeWithModelEventAndArrayDirective.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | var app = angular.module('directivesModule'); 4 | 5 | app.directive('isolateScopeWithModelEventAndArray', function () { 6 | return { 7 | restrict: 'EA', 8 | scope: { 9 | datasource: '=', 10 | add: '&', 11 | }, 12 | template: '' 13 | }; 14 | }); 15 | 16 | }()); -------------------------------------------------------------------------------- /Samples/Directives/js/isolateScopeWithStringDirective.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | var app = angular.module('directivesModule'); 4 | 5 | app.directive('isolateScopeWithString', function () { 6 | return { 7 | scope: { 8 | name: '@' //Two-way data binding 9 | }, 10 | template: 'Name: {{name}}' 11 | }; 12 | }); 13 | 14 | }()); -------------------------------------------------------------------------------- /Samples/Directives/js/lazyLoadDirective.js: -------------------------------------------------------------------------------- 1 | //Based upon the idea shown at https://www.youtube.com/watch?v=NlxqFADso6M 2 | (function() { 3 | 4 | var app = angular.module('directivesModule'); 5 | 6 | app.directive('lazyLoad', ['$interpolate', function ($interpolate) { 7 | 8 | var compile = function(tElem, tAttrs) { 9 | var interpolateFunc = $interpolate(tAttrs.lazyLoad); 10 | tAttrs.$set('lazyLoad', null); 11 | 12 | return function(scope, elem, attrs) { 13 | elem.on(attrs.trigger, function(event) { 14 | var attr = attrs.attribute; 15 | if (!elem.attr(attr)) { 16 | var val = interpolateFunc(scope); 17 | elem.attr(attr, val); 18 | } 19 | }); 20 | }; 21 | }; 22 | 23 | return { 24 | restrict: 'A', 25 | compile: compile 26 | }; 27 | }]); 28 | 29 | }()); -------------------------------------------------------------------------------- /Samples/Directives/js/linkDirective.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | var app = angular.module('directivesModule'); 4 | 5 | app.directive('linkDirective', function () { 6 | return { 7 | restrict: 'A', 8 | link: function ($scope, element, attrs) { 9 | element.on('click', function () { 10 | element.html('You clicked me!'); 11 | }); 12 | element.on('mouseenter', function () { 13 | element.css('background-color', 'yellow'); 14 | }); 15 | element.on('mouseleave', function () { 16 | element.css('background-color', 'white'); 17 | }); 18 | } 19 | }; 20 | }); 21 | 22 | }()); -------------------------------------------------------------------------------- /Samples/Directives/js/mapGeoLocationDirective.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | var app = angular.module('directivesModule', []); 4 | 5 | app.directive('mapGeoLocation', ['$window', function ($window) { 6 | var template = '

looking up geolocation...


' + 7 | '
', 8 | mapContainer = null, 9 | status = null; 10 | 11 | function link(scope, elem, attrs) { 12 | status = angular.element(document.getElementById('status')); 13 | mapContainer = angular.element(document.getElementById('map')); 14 | 15 | mapContainer.attr('style', 'height:' + scope.height + 'px;width:' + scope.width + 'px'); 16 | $window.navigator.geolocation.getCurrentPosition(mapLocation, geoError); 17 | } 18 | 19 | function mapLocation(pos) { 20 | status.html('Found your location! Longitude: ' + pos.coords.longitude + 21 | ' Latitude: ' + pos.coords.latitude); 22 | 23 | var latlng = new google.maps.LatLng(pos.coords.latitude, pos.coords.longitude); 24 | var options = { 25 | zoom: 15, 26 | center: latlng, 27 | mapTypeControl: true, 28 | mapTypeId: google.maps.MapTypeId.ROADMAP 29 | }; 30 | 31 | var map = new google.maps.Map(mapContainer[0], options); 32 | 33 | var marker = new google.maps.Marker({ 34 | position: latlng, 35 | map: map, 36 | title:"Your location" 37 | }); 38 | } 39 | 40 | function geoError(error) { 41 | status.html('failed lookup ' + error.message); 42 | } 43 | 44 | return { 45 | restrict: 'A', 46 | scope: { 47 | height: '@', 48 | width: '@' 49 | }, 50 | link: link, 51 | template: template 52 | }; 53 | 54 | }]); 55 | 56 | }()); -------------------------------------------------------------------------------- /Samples/Directives/js/sharedScopeDirective.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | var app = angular.module('directivesModule'); 4 | 5 | app.directive('sharedScope', function () { 6 | return { 7 | template: 'Name: {{customer.name}} Street: {{customer.street}}' 8 | }; 9 | }); 10 | 11 | }()); -------------------------------------------------------------------------------- /Samples/Directives/js/transclusionDirective.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | var app = angular.module('directivesModule'); 4 | 5 | app.directive('transclusion', function () { 6 | return { 7 | restrict: 'E', 8 | transclude: true, 9 | scope: { 10 | tasks: '=' 11 | }, 12 | controller: function ($scope) { 13 | $scope.addTask = function () { 14 | 15 | if (!$scope.tasks) $scope.tasks = []; 16 | 17 | $scope.tasks.push({ 18 | title: $scope.title 19 | }); 20 | 21 | }; 22 | }, 23 | template: '
Name:  ' + 24 | '' + 25 | '

' + 26 | '' + 27 | '
' 28 | }; 29 | }); 30 | 31 | }()); -------------------------------------------------------------------------------- /Samples/Directives/lazyLoad.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Lazy Attribute Loader Directive 5 | 9 | 10 | 11 | 12 |
14 | 15 |

Lazy Attribute Loader

16 | The lazy-load directive will cause attribute values to be loaded when a specific trigger 17 | (such as mouseenter) fires. 18 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /Samples/Directives/link.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Simple DOM Directive 5 | 6 | 7 | 8 |
10 | 11 |

Simple DOM Directive

12 | Mouse over the Click Me!. 13 |
Click Me!
14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /Samples/Directives/mapGeoLocation.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Geolocation Mapping Directive 5 | 6 | 7 | 8 |

Geolocation Mapping Directive

9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /Samples/Directives/sharedScope.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Shared Scope Directive 5 | 6 | 7 |
9 | 10 |

Shared Scope Directive

11 | Directive output: 12 |
13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /Samples/Directives/tableHelperController.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Table Helper DOM Directive 5 | 11 | 12 | 13 | 14 |
16 | 17 |

Table Helper DOM Directive

18 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /Samples/Directives/tableHelperDOM.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Table Helper DOM Directive 5 | 12 | 13 | 14 | 15 |
17 | 18 |

Table Helper DOM Directive

19 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /Samples/Directives/tableHelperDOMWithParse.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Table Helper DOM Directive with Parse 5 | 12 | 13 | 14 | 15 |
17 | 18 |

Table Helper DOM Directive with Parse

19 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /Samples/Directives/tableHelperDomWithNgModel.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Table Helper DOM Directive 5 | 11 | 12 | 13 | 14 |
16 | 17 |

Table Helper DOM Directive

18 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /Samples/Directives/transclusion.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Shared Scope Directive 5 | 6 | 7 | 8 |
10 | 11 |

Directive with Transclusion

12 |
13 | 14 |
15 | {{ task.title }} 16 |
17 |
18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /Samples/HybridSPADemo/.nuget/NuGet.Config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Samples/HybridSPADemo/.nuget/NuGet.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DanWahlin/AngularJSEndToEndCourseCode/12cf7f9f1213e481fa1c140f761e7e766a555845/Samples/HybridSPADemo/.nuget/NuGet.exe -------------------------------------------------------------------------------- /Samples/HybridSPADemo/HybridSPADemo.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2013 4 | VisualStudioVersion = 12.0.31101.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HybridSPADemo", "HybridSPADemo\HybridSPADemo.csproj", "{4CC4A2C2-2A1A-4B6F-9927-A6C29E8EC407}" 7 | EndProject 8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{25726D2F-1E4C-4820-B98E-FD1FA7CE95A1}" 9 | ProjectSection(SolutionItems) = preProject 10 | .nuget\NuGet.Config = .nuget\NuGet.Config 11 | .nuget\NuGet.exe = .nuget\NuGet.exe 12 | .nuget\NuGet.targets = .nuget\NuGet.targets 13 | EndProjectSection 14 | EndProject 15 | Global 16 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 17 | Debug|Any CPU = Debug|Any CPU 18 | Release|Any CPU = Release|Any CPU 19 | EndGlobalSection 20 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 21 | {4CC4A2C2-2A1A-4B6F-9927-A6C29E8EC407}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 22 | {4CC4A2C2-2A1A-4B6F-9927-A6C29E8EC407}.Debug|Any CPU.Build.0 = Debug|Any CPU 23 | {4CC4A2C2-2A1A-4B6F-9927-A6C29E8EC407}.Release|Any CPU.ActiveCfg = Release|Any CPU 24 | {4CC4A2C2-2A1A-4B6F-9927-A6C29E8EC407}.Release|Any CPU.Build.0 = Release|Any CPU 25 | EndGlobalSection 26 | GlobalSection(SolutionProperties) = preSolution 27 | HideSolutionNode = FALSE 28 | EndGlobalSection 29 | EndGlobal 30 | -------------------------------------------------------------------------------- /Samples/HybridSPADemo/HybridSPADemo/App_Start/RouteConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using System.Web.Mvc; 6 | using System.Web.Routing; 7 | 8 | namespace HybridSPADemo 9 | { 10 | public class RouteConfig 11 | { 12 | public static void RegisterRoutes(RouteCollection routes) 13 | { 14 | routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); 15 | 16 | routes.MapRoute( 17 | name: "Default", 18 | url: "{controller}/{action}/{id}", 19 | defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } 20 | ); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Samples/HybridSPADemo/HybridSPADemo/Controllers/ViewsController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using System.Web.Mvc; 6 | 7 | namespace HybridSPADemo.Controllers 8 | { 9 | public class ViewsController : Controller 10 | { 11 | // 12 | // GET: /Views/ 13 | public ActionResult Orders() 14 | { 15 | return View(); 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /Samples/HybridSPADemo/HybridSPADemo/Global.asax: -------------------------------------------------------------------------------- 1 | <%@ Application Codebehind="Global.asax.cs" Inherits="HybridSPADemo.MvcApplication" Language="C#" %> 2 | -------------------------------------------------------------------------------- /Samples/HybridSPADemo/HybridSPADemo/Global.asax.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using System.Web.Mvc; 6 | using System.Web.Routing; 7 | 8 | namespace HybridSPADemo 9 | { 10 | public class MvcApplication : System.Web.HttpApplication 11 | { 12 | protected void Application_Start() 13 | { 14 | AreaRegistration.RegisterAllAreas(); 15 | RouteConfig.RegisterRoutes(RouteTable.Routes); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Samples/HybridSPADemo/HybridSPADemo/HybridSPADemo.csproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | ProjectFiles 5 | True 6 | False 7 | False 8 | 9 | False 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | CurrentPage 18 | True 19 | False 20 | False 21 | False 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | True 31 | True 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /Samples/HybridSPADemo/HybridSPADemo/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("HybridSPADemo")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("HybridSPADemo")] 13 | [assembly: AssemblyCopyright("Copyright © 2014")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("b34ef850-90b2-41b6-8561-36227cf47428")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Revision and Build Numbers 33 | // by using the '*' as shown below: 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /Samples/HybridSPADemo/HybridSPADemo/Views/Shared/_Layout.cshtml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | My Merrill 5 |
6 |
7 | @RenderBody() 8 |
9 |
10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /Samples/HybridSPADemo/HybridSPADemo/Views/Shared/_ViewsLayout.cshtml: -------------------------------------------------------------------------------- 1 | @RenderBody() -------------------------------------------------------------------------------- /Samples/HybridSPADemo/HybridSPADemo/Views/Views/Orders.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "~/Views/Shared/_ViewsLayout.cshtml"; 3 | } 4 |

Orders

5 | CustomerID: {{ customerId }} 6 |
7 | 8 | @for (int i = 0; i < 10; i++) 9 | { 10 | 11 | 12 | 13 | } 14 |
@i
15 |
16 | Customers 17 | 18 | -------------------------------------------------------------------------------- /Samples/HybridSPADemo/HybridSPADemo/Views/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "~/Views/Shared/_Layout.cshtml"; 3 | } -------------------------------------------------------------------------------- /Samples/HybridSPADemo/HybridSPADemo/Views/web.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 |
7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /Samples/HybridSPADemo/HybridSPADemo/Web.Debug.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 17 | 18 | 29 | 30 | -------------------------------------------------------------------------------- /Samples/HybridSPADemo/HybridSPADemo/Web.Release.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 17 | 18 | 19 | 30 | 31 | -------------------------------------------------------------------------------- /Samples/HybridSPADemo/HybridSPADemo/Web.config: -------------------------------------------------------------------------------- 1 |  2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /Samples/HybridSPADemo/HybridSPADemo/app/views/customers.html: -------------------------------------------------------------------------------- 1 |
2 | Search: 3 |
4 |

Customers:

5 | 6 | 7 | 8 | 9 | 10 |
{{ cust.name }}{{ cust.total | currency }}
11 |
-------------------------------------------------------------------------------- /Samples/HybridSPADemo/HybridSPADemo/app/views/orders.html: -------------------------------------------------------------------------------- 1 |

Orders

2 | 3 | CustomerID: {{ customerId }} 4 |
5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
Baseball$9.99
Bat$19.99
15 | 16 |
17 | 18 | Customers -------------------------------------------------------------------------------- /Samples/HybridSPADemo/HybridSPADemo/customers.txt: -------------------------------------------------------------------------------- 1 | [ 2 | {"id": 1, "name":"Ted", "total": 5.996}, 3 | {"id": 2, "name":"Michelle", "total": 10.994}, 4 | {"id": 3, "name":"Zed", "total": 10.99}, 5 | {"id": 4, "name":"Tina", "total": 15.994} 6 | ] -------------------------------------------------------------------------------- /Samples/HybridSPADemo/HybridSPADemo/index.html: -------------------------------------------------------------------------------- 1 | 14 | 15 | 16 | 17 | Angular App 18 | 19 | 20 | 21 |

AngularJS Hybrid SPA (1 view loaded from server)

22 | 23 |
24 | 25 | 26 | 27 | 28 | 69 | 70 | -------------------------------------------------------------------------------- /Samples/HybridSPADemo/HybridSPADemo/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Samples/Pagination/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Client-Side Pagination 5 | 6 | 7 | 8 |
9 |
    10 |
  • 11 | {{customer.name}} 12 |
  • 13 |
14 |    15 | 16 |

17 | Page {{currentPage+1}} of {{totalPages}} 18 |
19 | 20 | 21 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /Samples/Routing/RoutingExample/Web.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /Samples/Routing/RoutingExample/app/app.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | var app = angular.module('demoApp',['ngRoute', 'ngAnimate']); 4 | 5 | app.config(function($routeProvider) { 6 | $routeProvider.when('/', 7 | { 8 | controller: 'CustomersController', 9 | templateUrl: 'app/views/customers.html', 10 | resolve: { 11 | customers: function (customersService) { 12 | return customersService.getCustomers(); 13 | } 14 | } 15 | }) 16 | .when('/orders/:customerId', 17 | { 18 | controller: 'OrdersController', 19 | templateUrl: '/app/views/orders.html', 20 | //templateUrl: 'templates/orders.html' //Load a local template 21 | caseInsensitiveMatch: true //Case doesn't matter for this route 22 | }) 23 | .otherwise({ redirectTo: '/' }); 24 | }); 25 | 26 | }()); 27 | 28 | -------------------------------------------------------------------------------- /Samples/Routing/RoutingExample/app/controllers/customersController.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | var CustomersController = function($scope, customers /* passed in by $routeProvider */) { 4 | $scope.customers = customers; 5 | }; 6 | 7 | CustomersController.$inject = ['$scope', 'customers']; 8 | 9 | angular.module('demoApp').controller('CustomersController', CustomersController); 10 | 11 | }()); 12 | 13 | -------------------------------------------------------------------------------- /Samples/Routing/RoutingExample/app/controllers/ordersController.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | var OrdersController = function($scope, $routeParams, ordersService) { 4 | $scope.customerId = $routeParams.customerId; 5 | 6 | function init() { 7 | ordersService.getCustomerOrders($scope.customerId).then(function (orders) { 8 | $scope.orders = orders; 9 | }); 10 | } 11 | 12 | init(); 13 | }; 14 | 15 | OrdersController.$inject = ['$scope', '$routeParams', 'ordersService']; 16 | 17 | angular.module('demoApp').controller('OrdersController', OrdersController); 18 | 19 | }()); -------------------------------------------------------------------------------- /Samples/Routing/RoutingExample/app/services/customersService.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | var customersFactory = function($http) { 4 | var factory = {}; 5 | 6 | factory.getCustomers = function() { 7 | return $http.get('/customers.json').then(function (custs) { 8 | return custs.data; 9 | }); 10 | }; 11 | 12 | return factory; 13 | }; 14 | 15 | customersFactory.$inject = ['$http']; 16 | 17 | angular.module('demoApp').factory('customersService', customersFactory); 18 | 19 | }()); -------------------------------------------------------------------------------- /Samples/Routing/RoutingExample/app/services/ordersService.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 3 | var ordersFactory = function ($http) { 4 | var factory = {}; 5 | 6 | factory.getCustomerOrders = function (id) { 7 | return $http.get('/orders.json').then(function (orders) { 8 | return orders.data; 9 | }); 10 | }; 11 | 12 | return factory; 13 | }; 14 | 15 | ordersFactory.$inject = ['$http']; 16 | 17 | angular.module('demoApp').factory('ordersService', ordersFactory); 18 | 19 | }()); -------------------------------------------------------------------------------- /Samples/Routing/RoutingExample/app/views/customers.html: -------------------------------------------------------------------------------- 1 |
2 | Search: 3 |
4 |

Customers:

5 | 6 | 7 | 8 | 9 | 10 |
{{ cust.name }}{{ cust.total | currency }}
11 |
-------------------------------------------------------------------------------- /Samples/Routing/RoutingExample/app/views/orders.html: -------------------------------------------------------------------------------- 1 |

Orders

2 | 3 | CustomerID: {{ customerId }} 4 |
5 | 6 | 7 | 8 | 9 | 10 |
{{order.product}}{{order.total | currency}}
11 | 12 |
13 | 14 | Customers -------------------------------------------------------------------------------- /Samples/Routing/RoutingExample/customers.json: -------------------------------------------------------------------------------- 1 | [ 2 | {"id": 1, "name":"Ted", "total": 5.996}, 3 | {"id": 2, "name":"Michelle", "total": 10.994}, 4 | {"id": 3, "name":"Zed", "total": 10.99}, 5 | {"id": 4, "name":"Tina", "total": 15.994} 6 | ] -------------------------------------------------------------------------------- /Samples/Routing/RoutingExample/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Angular App 5 | 6 | 7 | 8 |

Customers and Orders

9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /Samples/Routing/RoutingExample/orders.json: -------------------------------------------------------------------------------- 1 | [ 2 | {"id": 1, "product":"Golf Clubs", "total": 499.99}, 3 | {"id": 2, "product": "Shirt", "total": 39.99}, 4 | {"id": 3, "product":"Bicycle", "total": 299.99}, 5 | {"id": 4, "product":"Hat", "total": 29.99} 6 | ] -------------------------------------------------------------------------------- /Samples/Routing/RoutingExample/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular-routing", 3 | "version": "1.0.0", 4 | "description": "Sample App", 5 | "author": "Dan Wahlin", 6 | "dependencies": { 7 | "express": "^4.15.2" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Samples/Routing/RoutingExample/server.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var app = express(); 3 | 4 | app.use(express.static(__dirname)); 5 | 6 | app.listen(8000); 7 | console.log('Listening on port 8000'); -------------------------------------------------------------------------------- /Samples/Routing/RoutingExample/snippets.js: -------------------------------------------------------------------------------- 1 | $scope.customers = [ 2 | {"id": 1, "name":"Ted", "total": 5.996}, 3 | {"id": 2, "name":"Michelle", "total": 10.994}, 4 | {"id": 3, "name":"Zed", "total": 10.99}, 5 | {"id": 4, "name":"Tina", "total": 15.994} 6 | ]; 7 | 8 | 9 | app.config(function($routeProvider) { 10 | $routeProvider.when('/', 11 | { 12 | controller: 'CustomersController', 13 | templateUrl: 'app/views/customers.html' 14 | }) 15 | .when('/orders', 16 | { 17 | controller: 'OrdersController', 18 | templateUrl: 'app/views/orders.html' 19 | }) 20 | }); 21 | 22 | 23 | app.factory('customersFactory', function($http) { 24 | var factory = {}; 25 | factory.getCustomers = function() { 26 | return $http.get('/customers.json'); 27 | }; 28 | return factory; 29 | }); -------------------------------------------------------------------------------- /Samples/Routing/ui-router/README.md: -------------------------------------------------------------------------------- 1 | # Demonstration of AngularUI Router 2 | 3 | Code and demo for the scotch.io tutorial 4 | 5 | [AngularJS Routing Using UI-Router](http://scotch.io/tutorials/javascript/angular-routing-using-ui-router) -------------------------------------------------------------------------------- /Samples/Routing/ui-router/colors-list.html: -------------------------------------------------------------------------------- 1 |
    2 |
  • {{ color }}
  • 3 |
-------------------------------------------------------------------------------- /Samples/Routing/ui-router/customer-details.html: -------------------------------------------------------------------------------- 1 |

Selected Customer

2 | 3 | {{ selectedCustomer.name }} -------------------------------------------------------------------------------- /Samples/Routing/ui-router/customers.html: -------------------------------------------------------------------------------- 1 |
2 |

Customers

3 |

This page demonstrates multiple and named views.

4 |
5 | 6 |
7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 |
NameTotal
{{ cust.name }}${{ cust.total }}
25 |
26 | 27 | 28 |
29 |
30 |
31 | 32 | 33 |
-------------------------------------------------------------------------------- /Samples/Routing/ui-router/home.html: -------------------------------------------------------------------------------- 1 |
2 |

Home Page

3 |

This page demonstrates nested views.

4 | 5 | Colors List 6 | Description 7 | 8 |
9 | 10 |
-------------------------------------------------------------------------------- /Samples/Routing/ui-router/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 22 | 23 |
24 |
25 |
26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /Samples/Routing/ui-router/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular-routing", 3 | "version": "1.0.0", 4 | "description": "Sample App", 5 | "author": "Dan Wahlin", 6 | "dependencies": { 7 | "express": "^4.15.2" 8 | }, 9 | "scripts":{ 10 | "start": "node server.js" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Samples/Routing/ui-router/server.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var app = express(); 3 | 4 | app.use(express.static(__dirname)); 5 | 6 | app.listen(8000); 7 | console.log('Listening on port 8000'); -------------------------------------------------------------------------------- /Samples/Scopes/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Example - example-example106-production 6 | 13 | 14 | 15 | 16 | 29 | 30 | 31 | 32 |
33 |
34 | {{name}}! 35 |
36 |
37 |
    38 |
  1. {{name}}
  2. 39 |
40 |
41 |
42 | 43 | 44 | -------------------------------------------------------------------------------- /Samples/UnitTesting/app/app.js: -------------------------------------------------------------------------------- 1 | var reminderApp=angular.module('reminderApp',[]); 2 | 3 | reminderApp.controller('ReminderController', function($scope,reminderFactory) { 4 | 5 | $scope.reminders = reminderFactory.get(); 6 | 7 | $scope.$on("newReminder", function(event) { 8 | $scope.reminders = reminderFactory.get(); 9 | }); 10 | 11 | 12 | $scope.createReminder=function() { 13 | reminderFactory.put($scope.reminder); 14 | $scope.reminder = ""; 15 | } 16 | }); 17 | 18 | reminderApp.directive('customColor', function () { 19 | return { 20 | restrict: 'A', 21 | link: function (scope, elem, attrs) { 22 | elem.css({"background-color":attrs.customColor}); 23 | } 24 | } 25 | }); 26 | 27 | reminderApp.filter('truncate',function(){ 28 | return function(input,length){ 29 | return (input.length>length?input.substring(0,length):input); 30 | }; 31 | }); 32 | 33 | reminderApp.factory('reminderFactory',function($rootScope){ 34 | return { 35 | 36 | get:function(){ 37 | var reminders=[]; 38 | var keys=Object.keys(localStorage); 39 | for(var i=0;i li { 19 | display: inline; 20 | } 21 | 22 | .menu > li:before { 23 | content: "|"; 24 | padding-right: 0.3em; 25 | } 26 | 27 | .menu > li:nth-child(1):before { 28 | content: ""; 29 | padding: 0; 30 | } 31 | -------------------------------------------------------------------------------- /Samples/UnitTesting/app/lib/jasmine/MIT.LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2008-2011 Pivotal Labs 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /Samples/UnitTesting/app/lib/jasmine/jasmine_favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DanWahlin/AngularJSEndToEndCourseCode/12cf7f9f1213e481fa1c140f761e7e766a555845/Samples/UnitTesting/app/lib/jasmine/jasmine_favicon.png -------------------------------------------------------------------------------- /Samples/UnitTesting/app/reminders.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 19 | 20 | Angular Reminder App 21 | 22 | 23 |
24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 |
35 |
36 | 37 | 38 |
    39 |
  • 40 | {{reminder | truncate:20}} 41 |
  • 42 |
43 |
44 | 45 |
46 |
47 | 48 | -------------------------------------------------------------------------------- /Samples/UnitTesting/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "unit-testing", 3 | "description": "Unit Testing Demos", 4 | "devDependencies": { 5 | "phantomjs": "^2.1.7", 6 | "karma": "^1.5.0", 7 | "karma-jasmine": "^1.1.0", 8 | "karma-ng-scenario": "^1.0.0", 9 | "karma-chrome-launcher": "^2.0.0", 10 | "jasmine": "^2.5.3", 11 | "express": "^4.15.2" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Samples/UnitTesting/server.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var app = express(); 3 | 4 | app.use(express.static(__dirname)); 5 | 6 | app.listen(8000); 7 | console.log('Listening on port 8000'); -------------------------------------------------------------------------------- /Samples/UnitTesting/test/karma.conf.js: -------------------------------------------------------------------------------- 1 | module.exports = function(config) { 2 | 3 | config.set({ 4 | basePath : '../', 5 | frameworks: ['jasmine'], 6 | 7 | files : [ 8 | 'app/lib/angular.js', 9 | 'app/lib/angular-*.js', 10 | 'app/*.js', 11 | 'test/unit/*.js' 12 | ], 13 | 14 | autoWatch : true, 15 | 16 | browsers : ['Chrome'] 17 | 18 | }); 19 | 20 | }; 21 | -------------------------------------------------------------------------------- /Samples/UnitTesting/test/unit/controllersSpec.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('ReminderController Test', function() { 4 | var scope, controller; 5 | var mockFactory = { 6 | reminders:['reminder1','reminder2'], 7 | get: function (){ 8 | return this.reminders; 9 | }, 10 | put:function(content){ 11 | this.reminders.push(content); 12 | } 13 | }; 14 | 15 | beforeEach(function() { 16 | module('reminderApp'); 17 | inject(function($rootScope, $controller) { 18 | scope = $rootScope.$new(); 19 | controller = $controller("ReminderController", {$scope: scope, reminderFactory:mockFactory }); 20 | }); 21 | }); 22 | 23 | it('should return reminders array with 2 elements, add one, and return 3', function() { 24 | expect(scope.reminders.length).toBe(2); 25 | scope.reminder = "reminder3"; 26 | scope.createReminder(); 27 | expect(scope.reminders.length).toBe(3); 28 | }); 29 | }); -------------------------------------------------------------------------------- /Samples/UnitTesting/test/unit/directivesSpec.js: -------------------------------------------------------------------------------- 1 | describe('directive tests', function() { 2 | var scope, compile; 3 | 4 | beforeEach(function() { 5 | module('reminderApp'); 6 | inject(function($rootScope, $compile) { 7 | scope = $rootScope.$new(); 8 | compile = $compile; 9 | }); 10 | }); 11 | 12 | it('should set background to rgb(128, 128, 128)', function() { 13 | elem = angular.element("sample"); 14 | 15 | compile(elem)(scope); 16 | 17 | expect(elem.css("background-color")).toEqual('rgb(128, 128, 128)'); 18 | }); 19 | }); -------------------------------------------------------------------------------- /Samples/UnitTesting/test/unit/filtersSpec.js: -------------------------------------------------------------------------------- 1 | describe('filter tests', function() { 2 | 3 | beforeEach(function() { 4 | module('reminderApp'); 5 | }); 6 | 7 | it('should truncate the input to 10 characters', function() { 8 | inject(function(truncateFilter) { 9 | expect(truncateFilter('abcdefghijk',10).length).toBe(10); 10 | }); 11 | }); 12 | }); -------------------------------------------------------------------------------- /Samples/UnitTesting/test/unit/servicesSpec.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('reminderFactory tests', function (){ 4 | var factory; 5 | 6 | //excuted before each "it" is run. 7 | beforeEach(function (){ 8 | 9 | module('reminderApp'); 10 | 11 | //inject factory for testing 12 | inject(function(reminderFactory) { 13 | factory = reminderFactory; 14 | }); 15 | 16 | var store = {reminder1:'reminder1',reminder2:'reminder2',reminder3:'reminder3'}; 17 | 18 | spyOn(localStorage, 'getItem').and.callFake(function (key) { 19 | return store[key]; 20 | }); 21 | spyOn(localStorage, 'setItem').and.callFake(function (key, value) { 22 | return store[key] = value + ''; 23 | }); 24 | spyOn(localStorage, 'clear').and.callFake(function () { 25 | store = {}; 26 | }); 27 | spyOn(Object, 'keys').and.callFake(function (key) { 28 | var keys=[]; 29 | for(var key in store) 30 | keys.push(key); 31 | return keys; 32 | }); 33 | 34 | }); 35 | 36 | it('should have get and put functions', function () { 37 | expect(angular.isFunction(factory.get)).toBe(true); 38 | expect(angular.isFunction(factory.put)).toBe(true); 39 | }); 40 | 41 | it('should return 3 reminders initially', function (){ 42 | var result = factory.get(); 43 | expect(result.length).toBe(3); 44 | }); 45 | 46 | it('should return 4 reminders after adding one more', function (){ 47 | factory.put('reminder4'); 48 | var result = factory.get(); 49 | expect(result.length).toBe(4); 50 | }); 51 | 52 | }); 53 | -------------------------------------------------------------------------------- /Samples/Watches/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |

Reference, Equality, and Collection Watches

5 |
6 | 7 |
{{item}}
8 |
9 | 10 | Reference Watch: 11 |
{{referenceCount}}
12 | 13 | Equality Watch: 14 |
{{equalityCount}}
15 | 16 | Collection Watch: 17 |
{{collectionCount}}
18 | 19 | 20 |
21 | 22 | 23 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /Src/.nuget/NuGet.Config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Src/.nuget/NuGet.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DanWahlin/AngularJSEndToEndCourseCode/12cf7f9f1213e481fa1c140f761e7e766a555845/Src/.nuget/NuGet.exe -------------------------------------------------------------------------------- /Src/CustomerManager.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2013 4 | VisualStudioVersion = 12.0.30110.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CustomerManager", "CustomerManager\CustomerManager.csproj", "{9070F180-9D2C-44CD-86C7-0EFB3918D2F0}" 7 | EndProject 8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{AF7DC5C3-E97F-4405-B681-D13A4FF7DCF3}" 9 | ProjectSection(SolutionItems) = preProject 10 | .nuget\NuGet.Config = .nuget\NuGet.Config 11 | .nuget\NuGet.exe = .nuget\NuGet.exe 12 | .nuget\NuGet.targets = .nuget\NuGet.targets 13 | EndProjectSection 14 | EndProject 15 | Global 16 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 17 | Debug|Any CPU = Debug|Any CPU 18 | Release|Any CPU = Release|Any CPU 19 | EndGlobalSection 20 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 21 | {9070F180-9D2C-44CD-86C7-0EFB3918D2F0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 22 | {9070F180-9D2C-44CD-86C7-0EFB3918D2F0}.Debug|Any CPU.Build.0 = Debug|Any CPU 23 | {9070F180-9D2C-44CD-86C7-0EFB3918D2F0}.Release|Any CPU.ActiveCfg = Release|Any CPU 24 | {9070F180-9D2C-44CD-86C7-0EFB3918D2F0}.Release|Any CPU.Build.0 = Release|Any CPU 25 | {CEE64AD2-A800-49D8-8A30-06CAFB902397}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 26 | {CEE64AD2-A800-49D8-8A30-06CAFB902397}.Debug|Any CPU.Build.0 = Debug|Any CPU 27 | {CEE64AD2-A800-49D8-8A30-06CAFB902397}.Release|Any CPU.ActiveCfg = Release|Any CPU 28 | {CEE64AD2-A800-49D8-8A30-06CAFB902397}.Release|Any CPU.Build.0 = Release|Any CPU 29 | EndGlobalSection 30 | GlobalSection(SolutionProperties) = preSolution 31 | HideSolutionNode = FALSE 32 | EndGlobalSection 33 | EndGlobal 34 | -------------------------------------------------------------------------------- /Src/CustomerManager/App_Start/BreezeWebApiConfig.cs: -------------------------------------------------------------------------------- 1 | using System.Web.Http; 2 | 3 | [assembly: WebActivator.PreApplicationStartMethod( 4 | typeof(CustomerManager.App_Start.BreezeWebApiConfig), "RegisterBreezePreStart")] 5 | namespace CustomerManager.App_Start { 6 | /// 7 | /// Inserts the Breeze Web API controller route at the front of all Web API routes 8 | /// 9 | /// 10 | /// This class is discovered and run during startup; see 11 | /// http://blogs.msdn.com/b/davidebb/archive/2010/10/11/light-up-your-nupacks-with-startup-code-and-webactivator.aspx 12 | /// 13 | public static class BreezeWebApiConfig { 14 | 15 | public static void RegisterBreezePreStart() { 16 | GlobalConfiguration.Configuration.Routes.MapHttpRoute( 17 | name: "BreezeApi", 18 | routeTemplate: "breeze/{controller}/{action}" 19 | ); 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /Src/CustomerManager/App_Start/WebApiConfig.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using Newtonsoft.Json.Serialization; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Web; 7 | using System.Web.Http; 8 | using System.Web.Http.Controllers; 9 | 10 | namespace CustomerManager.App_Start 11 | { 12 | public static class WebApiConfig 13 | { 14 | public static void Register(HttpConfiguration config) 15 | { 16 | config.Routes.MapHttpRoute( 17 | name: "DefaultApi", 18 | routeTemplate: "api/{controller}/{action}/{id}", 19 | defaults: new { id = RouteParameter.Optional } 20 | ); 21 | 22 | config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); 23 | config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; 24 | 25 | // Remove default XML handler 26 | var matches = config.Formatters 27 | .Where(f => f.SupportedMediaTypes 28 | .Where(m => m.MediaType.ToString() == "application/xml" || 29 | m.MediaType.ToString() == "text/xml") 30 | .Count() > 0) 31 | .ToList(); 32 | foreach (var match in matches) 33 | config.Formatters.Remove(match); 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /Src/CustomerManager/Content/animations.css: -------------------------------------------------------------------------------- 1 | /* Animations */ 2 | .slide-animation-container { 3 | position:relative; 4 | } 5 | 6 | .slide-animation.ng-enter, .slide-animation.ng-leave { 7 | -moz-transition: 0.5s linear all; 8 | -o-transition: 0.5s linear all; 9 | -webkit-transition: 0.5s linear all; 10 | transition: 0.5s linear all; 11 | position: relative; 12 | /*top: 0; 13 | left: 0; 14 | right: 0;*/ 15 | height: 1000px; 16 | } 17 | 18 | .slide-animation.ng-enter { 19 | z-index:100; 20 | left:100px; 21 | opacity:0; 22 | } 23 | 24 | .slide-animation.ng-enter.ng-enter-active { 25 | left:0; 26 | opacity:1; 27 | } 28 | 29 | .slide-animation.ng-leave { 30 | z-index:101; 31 | opacity:1; 32 | left:0; 33 | } 34 | 35 | .slide-animation.ng-leave.ng-leave-active { 36 | left:-100px; 37 | opacity:0; 38 | } 39 | 40 | body.skip-animations * { 41 | -webkit-transition:none!important; 42 | -moz-transition:none!important; 43 | -o-transition:none!important; 44 | transition:none!important; 45 | } 46 | 47 | .show-hide-animation.ng-hide-add, 48 | .show-hide-animation.ng-hide-remove { 49 | -webkit-transition:all linear 0.3s; 50 | -moz-transition:all linear 0.3s; 51 | -o-transition:all linear 0.3s; 52 | transition:all linear 0.3s; 53 | display:block!important; 54 | height: 1000px; 55 | } 56 | 57 | .show-hide-animation.ng-hide-remove { 58 | opacity:0; 59 | } 60 | .show-hide-animation.ng-hide-remove.ng-hide-remove-active { 61 | opacity:1; 62 | } 63 | .show-hide-animation.ng-hide-add { 64 | opacity:1; 65 | } 66 | .show-hide-animation.ng-hide-add.ng-hide-add-active { 67 | opacity:0; 68 | } 69 | 70 | .repeat-animation.ng-enter, 71 | .repeat-animation.ng-leave, 72 | .repeat-animation.ng-move { 73 | -webkit-transition: 0.5s linear all; 74 | -moz-transition: 0.5s linear all; 75 | -o-transition: 0.5s linear all; 76 | transition: 0.5s linear all; 77 | position:relative; 78 | } 79 | 80 | .repeat-animation.ng-enter { 81 | left:10px; 82 | opacity:0; 83 | } 84 | .repeat-animation.ng-enter.ng-enter-active { 85 | left:0; 86 | opacity:1; 87 | } 88 | 89 | .repeat-animation.ng-leave { 90 | left:10px; 91 | opacity:1; 92 | } 93 | .repeat-animation.ng-leave.ng-leave-active { 94 | left:-10px; 95 | opacity:0; 96 | } 97 | 98 | .repeat-animation.ng-move { 99 | opacity:0.5; 100 | } 101 | .repeat-animation.ng-move.ng-move-active { 102 | opacity:1; 103 | } -------------------------------------------------------------------------------- /Src/CustomerManager/Content/images/ColorPalette.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DanWahlin/AngularJSEndToEndCourseCode/12cf7f9f1213e481fa1c140f761e7e766a555845/Src/CustomerManager/Content/images/ColorPalette.png -------------------------------------------------------------------------------- /Src/CustomerManager/Content/images/CourseLogoYellow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DanWahlin/AngularJSEndToEndCourseCode/12cf7f9f1213e481fa1c140f761e7e766a555845/Src/CustomerManager/Content/images/CourseLogoYellow.png -------------------------------------------------------------------------------- /Src/CustomerManager/Content/images/angularShield.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DanWahlin/AngularJSEndToEndCourseCode/12cf7f9f1213e481fa1c140f761e7e766a555845/Src/CustomerManager/Content/images/angularShield.png -------------------------------------------------------------------------------- /Src/CustomerManager/Content/images/appFolders.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DanWahlin/AngularJSEndToEndCourseCode/12cf7f9f1213e481fa1c140f761e7e766a555845/Src/CustomerManager/Content/images/appFolders.png -------------------------------------------------------------------------------- /Src/CustomerManager/Content/images/customerApp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DanWahlin/AngularJSEndToEndCourseCode/12cf7f9f1213e481fa1c140f761e7e766a555845/Src/CustomerManager/Content/images/customerApp.png -------------------------------------------------------------------------------- /Src/CustomerManager/Content/images/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DanWahlin/AngularJSEndToEndCourseCode/12cf7f9f1213e481fa1c140f761e7e766a555845/Src/CustomerManager/Content/images/favicon.ico -------------------------------------------------------------------------------- /Src/CustomerManager/Content/images/female.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DanWahlin/AngularJSEndToEndCourseCode/12cf7f9f1213e481fa1c140f761e7e766a555845/Src/CustomerManager/Content/images/female.png -------------------------------------------------------------------------------- /Src/CustomerManager/Content/images/male.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DanWahlin/AngularJSEndToEndCourseCode/12cf7f9f1213e481fa1c140f761e7e766a555845/Src/CustomerManager/Content/images/male.png -------------------------------------------------------------------------------- /Src/CustomerManager/Content/images/people.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DanWahlin/AngularJSEndToEndCourseCode/12cf7f9f1213e481fa1c140f761e7e766a555845/Src/CustomerManager/Content/images/people.png -------------------------------------------------------------------------------- /Src/CustomerManager/Content/images/report.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DanWahlin/AngularJSEndToEndCourseCode/12cf7f9f1213e481fa1c140f761e7e766a555845/Src/CustomerManager/Content/images/report.png -------------------------------------------------------------------------------- /Src/CustomerManager/Content/images/spinner.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DanWahlin/AngularJSEndToEndCourseCode/12cf7f9f1213e481fa1c140f761e7e766a555845/Src/CustomerManager/Content/images/spinner.gif -------------------------------------------------------------------------------- /Src/CustomerManager/CustomerManager.csproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | ProjectFiles 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | SpecificPage 13 | True 14 | False 15 | False 16 | False 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | False 26 | True 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /Src/CustomerManager/Global.asax: -------------------------------------------------------------------------------- 1 | <%@ Application Codebehind="Global.asax.cs" Inherits="CustomerManager.Global" Language="C#" %> 2 | -------------------------------------------------------------------------------- /Src/CustomerManager/Global.asax.cs: -------------------------------------------------------------------------------- 1 | using CustomerManager.App_Start; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Web; 6 | using System.Web.Http; 7 | using System.Web.Security; 8 | using System.Web.SessionState; 9 | 10 | namespace CustomerManager 11 | { 12 | public class Global : System.Web.HttpApplication 13 | { 14 | 15 | protected void Application_Start(object sender, EventArgs e) 16 | { 17 | WebApiConfig.Register(GlobalConfiguration.Configuration); 18 | } 19 | 20 | protected void Session_Start(object sender, EventArgs e) 21 | { 22 | 23 | } 24 | 25 | protected void Application_BeginRequest(object sender, EventArgs e) 26 | { 27 | 28 | } 29 | 30 | protected void Application_AuthenticateRequest(object sender, EventArgs e) 31 | { 32 | 33 | } 34 | 35 | protected void Application_Error(object sender, EventArgs e) 36 | { 37 | 38 | } 39 | 40 | protected void Session_End(object sender, EventArgs e) 41 | { 42 | 43 | } 44 | 45 | protected void Application_End(object sender, EventArgs e) 46 | { 47 | 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /Src/CustomerManager/Model/Customer.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using Newtonsoft.Json.Converters; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.ComponentModel.DataAnnotations; 6 | using System.Linq; 7 | using System.Web; 8 | 9 | namespace CustomerManager.Model 10 | { 11 | public class Customer 12 | { 13 | public int Id { get; set; } 14 | [StringLength(50)] 15 | public string FirstName { get; set; } 16 | [StringLength(50)] 17 | public string LastName { get; set; } 18 | [StringLength(100)] 19 | public string Email { get; set; } 20 | [StringLength(1000)] 21 | public string Address { get; set; } 22 | [StringLength(50)] 23 | public string City { get; set; } 24 | public State State { get; set; } 25 | public int StateId { get; set; } 26 | public int Zip { get; set; } 27 | [JsonConverter(typeof(StringEnumConverter))] 28 | public Gender Gender { get; set; } 29 | public ICollection Orders { get; set; } 30 | } 31 | 32 | public enum Gender 33 | { 34 | Female, 35 | Male 36 | } 37 | } -------------------------------------------------------------------------------- /Src/CustomerManager/Model/CustomerSummary.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using Newtonsoft.Json.Converters; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Web; 7 | 8 | namespace CustomerManager.Model 9 | { 10 | public class CustomerSummary 11 | { 12 | public int Id { get; set; } 13 | public string FirstName { get; set; } 14 | public string LastName { get; set; } 15 | public string City { get; set; } 16 | public State State { get; set; } 17 | public int OrderCount { get; set; } 18 | [JsonConverter(typeof(StringEnumConverter))] 19 | public Gender Gender { get; set; } 20 | } 21 | } -------------------------------------------------------------------------------- /Src/CustomerManager/Model/OperationStatus.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | 4 | namespace CustomerManager.Model 5 | { 6 | [DebuggerDisplay("Status: {Status}")] 7 | public class OperationStatus 8 | { 9 | public bool Status { get; set; } 10 | public int RecordsAffected { get; set; } 11 | public string Message { get; set; } 12 | public Object OperationId { get; set; } 13 | public string ExceptionMessage { get; set; } 14 | public string ExceptionStackTrace { get; set; } 15 | public string ExceptionInnerMessage { get; set; } 16 | public string ExceptionInnerStackTrace { get; set; } 17 | 18 | public static OperationStatus CreateFromException(string message, Exception ex) 19 | { 20 | OperationStatus opStatus = new OperationStatus 21 | { 22 | Status = false, 23 | Message = message, 24 | OperationId = null 25 | }; 26 | 27 | if (ex != null) 28 | { 29 | opStatus.ExceptionMessage = ex.Message; 30 | opStatus.ExceptionStackTrace = ex.StackTrace; 31 | opStatus.ExceptionInnerMessage = (ex.InnerException == null) ? null : ex.InnerException.Message; 32 | opStatus.ExceptionInnerStackTrace = (ex.InnerException == null) ? null : ex.InnerException.StackTrace; 33 | } 34 | return opStatus; 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Src/CustomerManager/Model/Order.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Linq; 5 | using System.Web; 6 | 7 | namespace CustomerManager.Model 8 | { 9 | public class Order 10 | { 11 | public int Id { get; set; } 12 | [StringLength(50)] 13 | public string Product { get; set; } 14 | public decimal Price { get; set; } 15 | public int Quantity { get; set; } 16 | public DateTime Date { get; set; } 17 | public int CustomerId { get; set; } 18 | public Customer Customer { get; set; } 19 | 20 | public Order Clone() 21 | { 22 | return (Order)this.MemberwiseClone(); 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /Src/CustomerManager/Model/State.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Linq; 5 | using System.Web; 6 | 7 | namespace CustomerManager.Model 8 | { 9 | public class State 10 | { 11 | public int Id { get; set; } 12 | [StringLength(2)] 13 | public string Abbreviation { get; set; } 14 | [StringLength(25)] 15 | public string Name { get; set; } 16 | } 17 | } -------------------------------------------------------------------------------- /Src/CustomerManager/Model/UserLogin.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | 6 | namespace CustomerManager.Model 7 | { 8 | public class UserLogin 9 | { 10 | public string UserName { get; set; } 11 | public string Password { get; set; } 12 | } 13 | } -------------------------------------------------------------------------------- /Src/CustomerManager/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("CustomerManager")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("CustomerManager")] 13 | [assembly: AssemblyCopyright("Copyright © 2013 Dan Wahlin")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("eebd9beb-e961-491f-a5e0-faa188f37e32")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Revision and Build Numbers 33 | // by using the '*' as shown below: 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /Src/CustomerManager/Repository/CustomerManagerContext.cs: -------------------------------------------------------------------------------- 1 | using CustomerManager.Model; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Configuration; 5 | using System.Data.Entity; 6 | using System.Linq; 7 | using System.Web; 8 | 9 | namespace CustomerManager.Repository 10 | { 11 | public class CustomerManagerContext : DbContext 12 | { 13 | public CustomerManagerContext() 14 | { 15 | Configuration.ProxyCreationEnabled = false; 16 | Configuration.LazyLoadingEnabled = false; 17 | } 18 | 19 | // DEVELOPMENT ONLY: initialize the database 20 | static CustomerManagerContext() 21 | { 22 | Database.SetInitializer(new CustomerManagerDatabaseInitializer()); 23 | } 24 | 25 | public DbSet Customers { get; set; } 26 | public DbSet Orders { get; set; } 27 | public DbSet States { get; set; } 28 | } 29 | } -------------------------------------------------------------------------------- /Src/CustomerManager/Repository/CustomerManagerDatabaseInitializer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Data.Entity; 4 | using System.Linq; 5 | using System.Text; 6 | 7 | namespace CustomerManager.Repository 8 | { 9 | ////DropCreateDatabaseIfModelChanges 10 | public class CustomerManagerDatabaseInitializer : DropCreateDatabaseAlways // re-creates every time the server starts 11 | { 12 | protected override void Seed(CustomerManagerContext context) 13 | { 14 | DataInitializer.Initialize(context); 15 | base.Seed(context); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Src/CustomerManager/Web.Debug.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 17 | 18 | 29 | 30 | -------------------------------------------------------------------------------- /Src/CustomerManager/Web.Release.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 17 | 18 | 19 | 30 | 31 | -------------------------------------------------------------------------------- /Src/CustomerManager/app/customersApp/animations/listAnimations.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | var wcAnimations = function () { 4 | var duration = 0.5; 5 | return { 6 | enter: function (element, done) { 7 | var random = Math.random() * 100; 8 | TweenMax.set(element, { opacity: 0, left: random + 'px' }); 9 | 10 | var random2 = Math.random(); 11 | TweenMax.to(element, duration, { opacity: 1, left: '0px', ease: Back.easeInOut, delay: random2, onComplete: done }); 12 | }, 13 | leave: function (element, done) { 14 | TweenMax.to(element, duration, { opacity: 0, left: '-50px', onComplete: done }); 15 | } 16 | }; 17 | }; 18 | 19 | angular.module('customersApp').animation('.card-animation', wcAnimations); 20 | 21 | }()); 22 | -------------------------------------------------------------------------------- /Src/CustomerManager/app/customersApp/controllers/aboutController.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 3 | var injectParams = []; 4 | 5 | var AboutController = function () { 6 | 7 | }; 8 | 9 | AboutController.$inject = injectParams; 10 | 11 | angular.module('customersApp').controller('AboutController', AboutController); 12 | 13 | }()); -------------------------------------------------------------------------------- /Src/CustomerManager/app/customersApp/controllers/customers/customerOrdersController.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 3 | var injectParams = ['$scope','$routeParams', '$window', 'dataService']; 4 | 5 | var CustomerOrdersController = function ($scope, $routeParams, $window, dataService) { 6 | var vm = this, 7 | customerId = ($routeParams.customerId) ? parseInt($routeParams.customerId) : 0; 8 | 9 | vm.customer = {}; 10 | vm.ordersTotal = 0.00; 11 | 12 | init(); 13 | 14 | function init() { 15 | if (customerId > 0) { 16 | dataService.getCustomer(customerId) 17 | .then(function (customer) { 18 | vm.customer = customer; 19 | $scope.$broadcast('customer', customer); 20 | }, function (error) { 21 | $window.alert("Sorry, an error occurred: " + error.message); 22 | }); 23 | } 24 | } 25 | }; 26 | 27 | CustomerOrdersController.$inject = injectParams; 28 | 29 | angular.module('customersApp').controller('CustomerOrdersController', CustomerOrdersController); 30 | 31 | }()); -------------------------------------------------------------------------------- /Src/CustomerManager/app/customersApp/controllers/loginController.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 3 | var injectParams = ['$location', '$routeParams', 'authService']; 4 | 5 | var LoginController = function ($location, $routeParams, authService) { 6 | var vm = this, 7 | path = '/'; 8 | 9 | vm.email = null; 10 | vm.password = null; 11 | vm.errorMessage = null; 12 | 13 | vm.login = function () { 14 | authService.login(vm.email, vm.password).then(function (status) { 15 | //$routeParams.redirect will have the route 16 | //they were trying to go to initially 17 | if (!status) { 18 | vm.errorMessage = 'Unable to login'; 19 | return; 20 | } 21 | 22 | if (status && $routeParams && $routeParams.redirect) { 23 | path = path + $routeParams.redirect; 24 | } 25 | 26 | $location.path(path); 27 | }); 28 | }; 29 | }; 30 | 31 | LoginController.$inject = injectParams; 32 | 33 | angular.module('customersApp') 34 | .controller('LoginController', LoginController); 35 | 36 | }()); -------------------------------------------------------------------------------- /Src/CustomerManager/app/customersApp/controllers/navbarController.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 3 | var injectParams = ['$scope', '$location', 'config', 'authService']; 4 | 5 | var NavbarController = function ($scope, $location, config, authService) { 6 | var vm = this, 7 | appTitle = 'Customer Management'; 8 | 9 | vm.isCollapsed = false; 10 | vm.appTitle = (config.useBreeze) ? appTitle + ' Breeze' : appTitle; 11 | 12 | vm.highlight = function (path) { 13 | return $location.path().substr(0, path.length) === path; 14 | }; 15 | 16 | vm.loginOrOut = function () { 17 | setLoginLogoutText(); 18 | var isAuthenticated = authService.user.isAuthenticated; 19 | if (isAuthenticated) { //logout 20 | authService.logout().then(function () { 21 | $location.path('/'); 22 | return; 23 | }); 24 | } 25 | redirectToLogin(); 26 | }; 27 | 28 | function redirectToLogin() { 29 | var path = '/login' + $location.$$path; 30 | $location.replace(); 31 | $location.path(path); 32 | } 33 | 34 | $scope.$on('loginStatusChanged', function (loggedIn) { 35 | setLoginLogoutText(loggedIn); 36 | }); 37 | 38 | $scope.$on('redirectToLogin', function () { 39 | redirectToLogin(); 40 | }); 41 | 42 | function setLoginLogoutText() { 43 | vm.loginLogoutText = (authService.user.isAuthenticated) ? 'Logout' : 'Login'; 44 | } 45 | 46 | setLoginLogoutText(); 47 | 48 | }; 49 | 50 | NavbarController.$inject = injectParams; 51 | 52 | angular.module('customersApp').controller('NavbarController', NavbarController); 53 | 54 | }()); 55 | -------------------------------------------------------------------------------- /Src/CustomerManager/app/customersApp/controllers/orders/orderChildController.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | var injectParams = ['$scope']; 4 | 5 | var OrderChildController = function ($scope) { 6 | var vm = this; 7 | 8 | vm.orderby = 'product'; 9 | vm.reverse = false; 10 | vm.ordersTotal = 0.00; 11 | vm.customer; 12 | 13 | init(); 14 | 15 | vm.setOrder = function (orderby) { 16 | if (orderby === vm.orderby) { 17 | vm.reverse = !vm.reverse; 18 | } 19 | vm.orderby = orderby; 20 | }; 21 | 22 | function init() { 23 | if ($scope.customer) { 24 | vm.customer = $scope.customer; 25 | updateTotal($scope.customer); 26 | } 27 | else { 28 | $scope.$on('customer', function (event, customer) { 29 | vm.customer = customer; 30 | updateTotal(customer); 31 | }); 32 | } 33 | } 34 | 35 | function updateTotal(customer) { 36 | var total = 0.00; 37 | for (var i = 0; i < customer.orders.length; i++) { 38 | var order = customer.orders[i]; 39 | total += order.orderTotal; 40 | } 41 | vm.ordersTotal = total; 42 | } 43 | }; 44 | 45 | OrderChildController.$inject = injectParams; 46 | 47 | angular.module('customersApp').controller('OrderChildController', OrderChildController); 48 | 49 | }()); -------------------------------------------------------------------------------- /Src/CustomerManager/app/customersApp/controllers/orders/ordersController.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 3 | var injectParams = ['$filter', '$window', 'dataService']; 4 | 5 | var OrdersController = function ($filter, $window, dataService) { 6 | var vm = this; 7 | 8 | vm.customers = []; 9 | vm.filteredCustomers; 10 | vm.filteredCount; 11 | 12 | //paging 13 | vm.totalRecords = 0; 14 | vm.pageSize = 10; 15 | vm.currentPage = 1; 16 | 17 | init(); 18 | 19 | vm.pageChanged = function () { 20 | getCustomers(); 21 | }; 22 | 23 | vm.searchTextChanged = function () { 24 | filterCustomersProducts(vm.searchText); 25 | }; 26 | 27 | function init() { 28 | //createWatches(); 29 | getCustomers(); 30 | } 31 | 32 | //function createWatches() { 33 | // //Watch searchText value and pass it and the customers to nameCityStateFilter 34 | // //Doing this instead of adding the filter to ng-repeat allows it to only be run once (rather than twice) 35 | // //while also accessing the filtered count via vm.filteredCount above 36 | 37 | // //Better to handle this using ng-change on . See searchTextChanged() function. 38 | // $scope.$watch("searchText", function (filterText) { 39 | // filterCustomersProducts(filterText); 40 | // }); 41 | //} 42 | 43 | function filterCustomersProducts(filterText) { 44 | vm.filteredCustomers = $filter("nameProductFilter")(vm.customers, filterText); 45 | vm.filteredCount = vm.filteredCustomers.length; 46 | } 47 | 48 | function getCustomers() { 49 | dataService.getCustomers(vm.currentPage - 1, vm.pageSize) 50 | .then(function (data) { 51 | vm.totalRecords = data.totalRecords; 52 | vm.customers = data.results; 53 | filterCustomersProducts(''); 54 | }, function (error) { 55 | $window.alert(error.message); 56 | }); 57 | } 58 | }; 59 | 60 | OrdersController.$inject = injectParams; 61 | 62 | angular.module('customersApp').controller('OrdersController', OrdersController); 63 | 64 | }()); 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /Src/CustomerManager/app/customersApp/directives/lazyLoader.js: -------------------------------------------------------------------------------- 1 | // 2 | (function () { 3 | // use this directive to delay assigning user input to the underlying 4 | // view model field until focus leaves the dom element. Useful for 5 | // delaying breeze validation until user enters all data (like when 6 | // entering dates) 7 | var lazyLoad = function () { 8 | return { 9 | restrict: 'A', //E = element, A = attribute, C = class, M = comment 10 | transclude: true, 11 | scope: { 12 | name: '@' 13 | }, 14 | link: function (scope, element, attrs) { 15 | element.bind('blur', function (e) { 16 | scope.$parent.$apply(function () { 17 | scope.$parent[scope.name] = element.val(); 18 | }); 19 | }); 20 | } 21 | }; 22 | }; 23 | 24 | angular.module('customersApp').directive('lazyLoad', lazyLoad); 25 | 26 | }()); -------------------------------------------------------------------------------- /Src/CustomerManager/app/customersApp/directives/wcUnique.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 3 | var injectParams = ['$q', 'dataService']; 4 | 5 | var wcUniqueDirective = function ($q, dataService) { 6 | 7 | var link = function (scope, element, attrs, ngModel) { 8 | ngModel.$asyncValidators.unique = function (modelValue, viewValue) { 9 | var deferred = $q.defer(), 10 | currentValue = modelValue || viewValue, 11 | key = attrs.wcUniqueKey, 12 | property = attrs.wcUniqueProperty; 13 | 14 | //First time the asyncValidators function is loaded the 15 | //key won't be set so ensure that we have 16 | //key and propertyName before checking with the server 17 | if (key && property) { 18 | dataService.checkUniqueValue(key, property, currentValue) 19 | .then(function (unique) { 20 | if (unique) { 21 | deferred.resolve(); //It's unique 22 | } 23 | else { 24 | deferred.reject(); //Add unique to $errors 25 | } 26 | }); 27 | return deferred.promise; 28 | } 29 | else { 30 | return $q.when(true); 31 | } 32 | }; 33 | }; 34 | 35 | return { 36 | restrict: 'A', 37 | require: 'ngModel', 38 | link: link 39 | }; 40 | }; 41 | 42 | wcUniqueDirective.$inject = injectParams; 43 | 44 | angular.module('customersApp').directive('wcUnique', wcUniqueDirective); 45 | 46 | }()); -------------------------------------------------------------------------------- /Src/CustomerManager/app/customersApp/filters/nameCityStateFilter.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 3 | var nameCityStateFilter = function () { 4 | 5 | return function (customers, filterValue) { 6 | if (!filterValue) return customers; 7 | 8 | var matches = []; 9 | filterValue = filterValue.toLowerCase(); 10 | for (var i = 0; i < customers.length; i++) { 11 | var cust = customers[i]; 12 | if (cust.firstName.toLowerCase().indexOf(filterValue) > -1 || 13 | cust.lastName.toLowerCase().indexOf(filterValue) > -1 || 14 | cust.city.toLowerCase().indexOf(filterValue) > -1 || 15 | cust.state.name.toLowerCase().indexOf(filterValue) > -1) { 16 | 17 | matches.push(cust); 18 | } 19 | } 20 | return matches; 21 | }; 22 | }; 23 | 24 | angular.module('customersApp').filter('nameCityStateFilter', nameCityStateFilter); 25 | 26 | }()); -------------------------------------------------------------------------------- /Src/CustomerManager/app/customersApp/filters/nameProductFilter.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 3 | var nameProductFilter = function () { 4 | 5 | function matchesProduct(customer, filterValue) { 6 | if (customer.orders) { 7 | for (var i = 0; i < customer.orders.length; i++) { 8 | if (customer.orders[i].product.toLowerCase().indexOf(filterValue) > -1) { 9 | return true; 10 | } 11 | } 12 | } 13 | return false; 14 | } 15 | 16 | return function (customers, filterValue) { 17 | if (!filterValue || !customers) return customers; 18 | 19 | var matches = []; 20 | filterValue = filterValue.toLowerCase(); 21 | for (var i = 0; i < customers.length; i++) { 22 | var cust = customers[i]; 23 | if (cust.firstName.toLowerCase().indexOf(filterValue) > -1 || 24 | cust.lastName.toLowerCase().indexOf(filterValue) > -1 || 25 | matchesProduct(cust, filterValue)) { 26 | 27 | matches.push(cust); 28 | } 29 | } 30 | return matches; 31 | }; 32 | }; 33 | 34 | angular.module('customersApp').filter('nameProductFilter', nameProductFilter); 35 | 36 | }()); -------------------------------------------------------------------------------- /Src/CustomerManager/app/customersApp/partials/modal.html: -------------------------------------------------------------------------------- 1 |  13 | -------------------------------------------------------------------------------- /Src/CustomerManager/app/customersApp/services/authService.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 3 | var injectParams = ['$http', '$rootScope']; 4 | 5 | var authFactory = function ($http, $rootScope) { 6 | var serviceBase = '/api/dataservice/', 7 | factory = { 8 | loginPath: '/login', 9 | user: { 10 | isAuthenticated: false, 11 | roles: null 12 | } 13 | }; 14 | 15 | factory.login = function (email, password) { 16 | return $http.post(serviceBase + 'login', { userLogin: { userName: email, password: password } }).then( 17 | function (results) { 18 | var loggedIn = results.data.status;; 19 | changeAuth(loggedIn); 20 | return loggedIn; 21 | }); 22 | }; 23 | 24 | factory.logout = function () { 25 | return $http.post(serviceBase + 'logout').then( 26 | function (results) { 27 | var loggedIn = !results.data.status; 28 | changeAuth(loggedIn); 29 | return loggedIn; 30 | }); 31 | }; 32 | 33 | factory.redirectToLogin = function () { 34 | $rootScope.$broadcast('redirectToLogin', null); 35 | }; 36 | 37 | function changeAuth(loggedIn) { 38 | factory.user.isAuthenticated = loggedIn; 39 | $rootScope.$broadcast('loginStatusChanged', loggedIn); 40 | } 41 | 42 | return factory; 43 | }; 44 | 45 | authFactory.$inject = injectParams; 46 | 47 | angular.module('customersApp').factory('authService', authFactory); 48 | 49 | }()); 50 | 51 | -------------------------------------------------------------------------------- /Src/CustomerManager/app/customersApp/services/config.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 3 | var value = { 4 | useBreeze: false 5 | }; 6 | 7 | angular.module('customersApp').value('config', value); 8 | 9 | }()); -------------------------------------------------------------------------------- /Src/CustomerManager/app/customersApp/services/dataService.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 3 | var injectParams = ['config', 'customersService', 'customersBreezeService']; 4 | 5 | var dataService = function (config, customersService, customersBreezeService) { 6 | return (config.useBreeze) ? customersBreezeService : customersService; 7 | }; 8 | 9 | dataService.$inject = injectParams; 10 | 11 | angular.module('customersApp').factory('dataService', dataService); 12 | 13 | }()); 14 | 15 | -------------------------------------------------------------------------------- /Src/CustomerManager/app/customersApp/services/httpInterceptors.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 3 | angular.module('customersApp') 4 | .config(['$httpProvider', function ($httpProvider) { 5 | 6 | var injectParams = ['$q', '$rootScope']; 7 | 8 | var httpInterceptor401 = function ($q, $rootScope) { 9 | 10 | var success = function (response) { 11 | return response; 12 | }; 13 | 14 | var error = function (res) { 15 | if (res.status === 401) { 16 | //Raise event so listener (navbarController) can act on it 17 | $rootScope.$broadcast('redirectToLogin', null); 18 | return $q.reject(res); 19 | } 20 | return $q.reject(res); 21 | }; 22 | 23 | return function (promise) { 24 | return promise.then(success, error); 25 | }; 26 | 27 | }; 28 | 29 | httpInterceptor401.$inject = injectParams; 30 | 31 | $httpProvider.interceptors.push(httpInterceptor401); 32 | 33 | }]); 34 | 35 | }()); -------------------------------------------------------------------------------- /Src/CustomerManager/app/customersApp/services/modalService.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 3 | var injectParams = ['$uibModal']; 4 | 5 | var modalService = function ($uibModal) { 6 | 7 | var modalDefaults = { 8 | backdrop: true, 9 | keyboard: true, 10 | modalFade: true, 11 | templateUrl: '/app/customersApp/partials/modal.html' 12 | }; 13 | 14 | var modalOptions = { 15 | closeButtonText: 'Close', 16 | actionButtonText: 'OK', 17 | headerText: 'Proceed?', 18 | bodyText: 'Perform this action?' 19 | }; 20 | 21 | this.showModal = function (customModalDefaults, customModalOptions) { 22 | if (!customModalDefaults) customModalDefaults = {}; 23 | customModalDefaults.backdrop = 'static'; 24 | return this.show(customModalDefaults, customModalOptions); 25 | }; 26 | 27 | this.show = function (customModalDefaults, customModalOptions) { 28 | //Create temp objects to work with since we're in a singleton service 29 | var tempModalDefaults = {}; 30 | var tempModalOptions = {}; 31 | 32 | //Map angular-ui modal custom defaults to modal defaults defined in this service 33 | angular.extend(tempModalDefaults, modalDefaults, customModalDefaults); 34 | 35 | //Map modal.html $scope custom properties to defaults defined in this service 36 | angular.extend(tempModalOptions, modalOptions, customModalOptions); 37 | 38 | if (!tempModalDefaults.controller) { 39 | tempModalDefaults.controller = function ($scope, $uibModalInstance) { 40 | $scope.modalOptions = tempModalOptions; 41 | $scope.modalOptions.ok = function (result) { 42 | $uibModalInstance.close('ok'); 43 | }; 44 | $scope.modalOptions.close = function (result) { 45 | $uibModalInstance.close('cancel'); 46 | }; 47 | }; 48 | 49 | tempModalDefaults.controller.$inject = ['$scope', '$uibModalInstance']; 50 | } 51 | 52 | return $uibModal.open(tempModalDefaults).result; 53 | }; 54 | }; 55 | 56 | modalService.$inject = injectParams; 57 | 58 | angular.module('customersApp').service('modalService', modalService); 59 | 60 | }()); -------------------------------------------------------------------------------- /Src/CustomerManager/app/customersApp/views/about.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |

About

5 |
6 |
7 |
8 |
9 |
Created by:
10 | 11 |
12 |
13 |
14 |
Blog:
15 | 16 |
17 |
18 | 22 |
23 | 27 |
28 |
29 |
30 | 31 | 32 | -------------------------------------------------------------------------------- /Src/CustomerManager/app/customersApp/views/customers/customerOrders.html: -------------------------------------------------------------------------------- 1 | 
2 |
3 |
4 |

  Customer Orders

5 |
6 |
7 |
8 |
9 |
10 |

Orders for {{ vm.customer.firstName + ' ' + vm.customer.lastName }}

11 | {{vm.customer.address}} 12 |
13 | {{vm.customer.city}}, {{vm.customer.state.name}} 14 |

15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | -------------------------------------------------------------------------------- /Src/CustomerManager/app/customersApp/views/login.html: -------------------------------------------------------------------------------- 1 | 
2 |
3 |
4 |

Login

5 |
6 |
7 | 52 |
53 |
54 |
55 | 56 | -------------------------------------------------------------------------------- /Src/CustomerManager/app/customersApp/views/orders/orders.html: -------------------------------------------------------------------------------- 1 | 
2 |
3 |
4 |

  All Customer Orders

5 |
6 |
7 |
8 |
9 |
10 | 11 |
12 | 15 |
16 |
17 |
18 |
19 |
20 |
21 | 28 |
29 |
30 |

No customers found

31 |
32 |
33 |
34 |
35 |
    42 | 43 |
    Showing {{ vm.filteredCount }} of {{ vm.totalRecords}} total customers
    44 |
    45 |
    46 |
    47 |
    48 |


    49 |
    50 | 51 | -------------------------------------------------------------------------------- /Src/CustomerManager/app/customersApp/views/orders/ordersTable.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 16 | 17 | 18 | 21 | 24 | 27 | 30 | 33 | 34 | 35 | 38 | 41 | 42 | 43 |
    ProductDateQuantityUnit PriceTotal
    14 |
    No orders found
    15 |
    19 | {{ order.product }} 20 | 22 | {{ order.date | date:'MM/dd/yyyy' }} 23 | 25 | {{ order.quantity }} 26 | 28 | {{ order.price | currency }} 29 | 31 | {{ order.orderTotal | currency }} 32 |
    36 |   37 | 39 | {{ vm.customer.ordersTotal | currency }} 40 |
    -------------------------------------------------------------------------------- /Src/CustomerManager/app/wc.directives/directives/lazyLoader.js: -------------------------------------------------------------------------------- 1 | // 2 | (function () { 3 | // use this directive to delay assigning user input to the underlying 4 | // view model field until focus leaves the dom element. Useful for 5 | // delaying breeze validation until user enters all data (like when 6 | // entering dates) 7 | var lazyLoad = function () { 8 | return { 9 | restrict: 'A', //E = element, A = attribute, C = class, M = comment 10 | transclude: true, 11 | scope: { 12 | name: '@' 13 | }, 14 | link: function (scope, element, attrs) { 15 | element.bind('blur', function (e) { 16 | scope.$parent.$apply(function () { 17 | scope.$parent[scope.name] = element.val(); 18 | }); 19 | }); 20 | } 21 | }; 22 | }; 23 | 24 | angular.module('customersApp').directive('lazyLoad', lazyLoad); 25 | 26 | }()); -------------------------------------------------------------------------------- /Src/CustomerManager/app/wc.directives/directives/menuHighlighter.js: -------------------------------------------------------------------------------- 1 | /* 2 | Thanks to Karl-Gustav for creating the autoActive directive 3 | to simplify highlighting
  • elements in a menu based on the path 4 | View the original version of the autoActive directive at 5 | https://github.com/Karl-Gustav/autoActive 6 | 7 | This version renames the directive and does some minor code restructuring and changes. 8 | */ 9 | 10 | (function () { 11 | 12 | var injectParams = ['$location']; 13 | 14 | var menuHighlighter = function ($location) { 15 | 16 | var link = function (scope, element) { 17 | function setActive() { 18 | var path = $location.path(); 19 | var className = scope.highlightClassName || 'active'; 20 | 21 | if (path) { 22 | angular.forEach(element.find('li'), function (li) { 23 | var anchor = li.querySelector('a'); 24 | //Get href from href attribute or data-href in cases where href isn't used (such as login) 25 | var href = (anchor && anchor.href) ? anchor.href : 26 | anchor.getAttribute('data-href').replace('#!', ''); 27 | //Get value after hash 28 | var trimmedHref = href.substr(href.indexOf('#!/') + 2, href.length); 29 | //Convert path to same length as trimmedHref 30 | var basePath = path.substr(0, trimmedHref.length); 31 | 32 | //See if trimmedHref and basePath match. If so, then highlight that item 33 | if (trimmedHref === basePath) { 34 | angular.element(li).addClass(className); 35 | } else { 36 | angular.element(li).removeClass(className); 37 | } 38 | }); 39 | } 40 | } 41 | 42 | setActive(); 43 | 44 | //Monitor location changes 45 | scope.$on('$locationChangeSuccess', setActive); 46 | }; 47 | 48 | return { 49 | restrict: 'A', 50 | scope: { 51 | highlightClassName: '@' 52 | }, 53 | link: link 54 | } 55 | } 56 | 57 | menuHighlighter.$inject = injectParams; 58 | 59 | angular.module('wc.directives').directive('menuHighlighter', menuHighlighter); 60 | 61 | }()); -------------------------------------------------------------------------------- /Src/CustomerManager/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DanWahlin/AngularJSEndToEndCourseCode/12cf7f9f1213e481fa1c140f761e7e766a555845/Src/CustomerManager/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /Src/CustomerManager/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DanWahlin/AngularJSEndToEndCourseCode/12cf7f9f1213e481fa1c140f761e7e766a555845/Src/CustomerManager/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /Src/CustomerManager/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DanWahlin/AngularJSEndToEndCourseCode/12cf7f9f1213e481fa1c140f761e7e766a555845/Src/CustomerManager/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /Src/CustomerManager/gulpfile.js: -------------------------------------------------------------------------------- 1 | var gulp = require('gulp'), 2 | uglify = require('gulp-uglify'), 3 | concat = require('gulp-concat'), 4 | plumber = require('gulp-plumber'), 5 | templateCache = require('gulp-angular-templatecache'), 6 | //sass = require('gulp-sass'), 7 | //csso = require('gulp-csso'), 8 | dist = 'Scripts/dist'; 9 | 10 | //gulp.task('sass', function () { 11 | // gulp.src('Content/styles.scss') 12 | // .pipe(plumber()) 13 | // .pipe(sass({ errLogToConsole: true })) 14 | // .pipe(csso()) 15 | // .pipe(gulp.dest('Content')); 16 | //}); 17 | 18 | gulp.task('compressScripts', function () { 19 | gulp.src([ 20 | 'app/**/*.js' 21 | ]) 22 | .pipe(plumber()) 23 | .pipe(concat('scripts.min.js')) 24 | .pipe(uglify()) 25 | .pipe(gulp.dest(dist)); 26 | }); 27 | 28 | gulp.task('templates', function () { 29 | gulp.src('app/customersApp/views/**/*.html') 30 | .pipe(plumber()) 31 | .pipe(templateCache({ root: 'app/customersApp/views', module: 'customersApp' })) 32 | .pipe(gulp.dest(dist)); 33 | }); 34 | 35 | gulp.task('watch', function () { 36 | 37 | //gulp.watch('Content/*.scss', ['sass']); 38 | 39 | gulp.watch(['app/**/*.js'], 40 | ['compressScripts']); 41 | 42 | }); 43 | 44 | gulp.task('default', ['compressScripts', 'templates', 'watch']); 45 | -------------------------------------------------------------------------------- /Src/CustomerManager/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "customer-manager-standard", 3 | "author": "Dan Wahlin", 4 | "version": "1.0.0", 5 | "scripts": { 6 | "start": "node server/server.js" 7 | }, 8 | "dependencies": { 9 | "express": "^4.15.2", 10 | "pug": "^2.0.0-beta11", 11 | "mongoose": "^4.9.1", 12 | "cookie-parser": "^1.4.3", 13 | "body-parser": "^1.17.1", 14 | "express-session": "^1.15.1", 15 | "errorhandler": "^1.5.0", 16 | "csurf": "^1.9.0" 17 | }, 18 | "devDependencies": { 19 | "gulp": "^3.9.1", 20 | "gulp-angular-templatecache": "^2.0.0", 21 | "gulp-concat": "^2.6.1", 22 | "gulp-sass": "^3.1.0", 23 | "gulp-csso": "^3.0.0", 24 | "gulp-plumber": "^1.1.0", 25 | "gulp-uglify": "^2.1.1", 26 | "phantomjs-prebuilt": "2.1.14", 27 | "karma": "^1.5.0", 28 | "karma-jasmine": "^1.1.0", 29 | "karma-ng-scenario": "^1.0.0", 30 | "karma-chrome-launcher": "^2.0.0", 31 | "jasmine": "^2.5.3" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Src/CustomerManager/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /Src/CustomerManager/server/initMongoDB.bat: -------------------------------------------------------------------------------- 1 | @ECHO off 2 | c:\mongodb\bin\mongo.exe %CD%\initMongoData.js 3 | 4 | ECHO - 5 | ECHO Your data is loaded 6 | pause -------------------------------------------------------------------------------- /Src/CustomerManager/server/initMongoDB.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | scriptDir=$(dirname $0) 4 | 5 | mongo ${scriptDir}/initMongoData.js 6 | 7 | echo - 8 | echo Your data is loaded 9 | read -p "Press [Enter] to exit..." -------------------------------------------------------------------------------- /Src/CustomerManager/server/lib/protectJSON.js: -------------------------------------------------------------------------------- 1 | // JSON vulnerability protection 2 | // we prepend the data with ")]},\n", which will be stripped by $http in AngularJS 3 | // From angular-app (https://github.com/angular-app/angular-app), by Pawel Kozlowski & Peter Bacon Darwin 4 | module.exports = function(req, res, next) { 5 | var _send = res.send; 6 | res.send = function(body) { 7 | var contentType = res.getHeader('Content-Type'); 8 | if ( contentType && contentType.indexOf('application/json') !== -1 ) { 9 | if (2 == arguments.length) { 10 | // res.send(body, status) backwards compat 11 | if ('number' != typeof body && 'number' == typeof arguments[1]) { 12 | this.statusCode = arguments[1]; 13 | } else { 14 | this.statusCode = body; 15 | body = arguments[1]; 16 | } 17 | } 18 | body = ")]}',\n" + body; 19 | return _send.call(res, body); 20 | } 21 | _send.apply(res, arguments); 22 | }; 23 | next(); 24 | }; -------------------------------------------------------------------------------- /Src/CustomerManager/server/models/customer.js: -------------------------------------------------------------------------------- 1 | var mongoose = require('mongoose') 2 | , Schema = mongoose.Schema 3 | , ObjectId = Schema.ObjectId; 4 | 5 | 6 | var SettingsSchema = new Schema({ 7 | collectionName : { 8 | type : String, required: true, trim: true, default: 'customers' 9 | }, 10 | nextSeqNumber: { 11 | type: Number, default: 1 12 | } 13 | }); 14 | 15 | var OrderSchema = new Schema({ 16 | product : { 17 | type : String, required: true, trim: true 18 | }, 19 | price : { 20 | type : Number, 21 | }, 22 | quantity : { 23 | type : Number, 24 | } 25 | }); 26 | 27 | var CustomerSchema = new Schema({ 28 | firstName : { 29 | type : String, required: true, trim: true 30 | }, 31 | lastName : { 32 | type : String, required: true, trim: true 33 | }, 34 | email : { 35 | type : String, required: true, trim: true 36 | }, 37 | address : { 38 | type : String, required: true, trim: true 39 | }, 40 | city : { 41 | type : String, required: true, trim: true 42 | }, 43 | stateId : { 44 | type : Number, required: true 45 | }, 46 | state : { 47 | id : { 48 | type : Number 49 | }, 50 | abbreviation : { 51 | type : String, required: true, trim: true 52 | }, 53 | name : { 54 | type : String, required: true, trim: true 55 | } 56 | }, 57 | zip : { 58 | type : Number, required: true 59 | }, 60 | gender : { 61 | type : String, 62 | }, 63 | id : { 64 | type : Number, required: true, unique: true 65 | }, 66 | orderCount : { 67 | type : Number, 68 | }, 69 | orders: [OrderSchema], 70 | }); 71 | 72 | CustomerSchema.index({ id: 1, type: 1 }); // schema level 73 | 74 | // I make sure this is the last pre-save middleware (just in case) 75 | var Settings = mongoose.model('settings', SettingsSchema); 76 | 77 | CustomerSchema.pre('save', function(next) { 78 | var doc = this; 79 | // Calculate the next id on new Customers only. 80 | if (this.isNew) { 81 | Settings.findOneAndUpdate( {"collectionName": "customers"}, { $inc: { nextSeqNumber: 1 } }, function (err, settings) { 82 | if (err) next(err); 83 | doc.id = settings.nextSeqNumber - 1; // substract 1 because I need the 'current' sequence number, not the next 84 | next(); 85 | }); 86 | } else { 87 | next(); 88 | } 89 | }); 90 | 91 | exports.CustomerSchema = CustomerSchema; 92 | module.exports = mongoose.model('Customer', CustomerSchema); 93 | -------------------------------------------------------------------------------- /Src/CustomerManager/server/models/state.js: -------------------------------------------------------------------------------- 1 | var mongoose = require('mongoose') 2 | , Schema = mongoose.Schema 3 | , ObjectId = Schema.ObjectId; 4 | 5 | var StateSchema = new Schema({ 6 | id : { 7 | type : Number, required: true 8 | }, 9 | abbreviation : { 10 | type : String, required: true, trim: true 11 | }, 12 | name : { 13 | type : String, required: true, trim: true 14 | } 15 | }); 16 | 17 | exports.StateSchema = StateSchema; 18 | module.exports = mongoose.model('State', StateSchema); 19 | 20 | -------------------------------------------------------------------------------- /Src/CustomerManager/server/routes/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | * GET home page. 3 | */ 4 | 5 | exports.index = function(req, res){ 6 | res.render('index'); 7 | }; 8 | -------------------------------------------------------------------------------- /Src/CustomerManager/server/server.js: -------------------------------------------------------------------------------- 1 | var express = require('express'), 2 | cookieParser = require('cookie-parser'), 3 | bodyParser = require('body-parser'), 4 | session = require('express-session'), 5 | errorhandler = require('errorhandler'), 6 | csrf = require('csurf'), 7 | routes = require('./routes'), 8 | api = require('./routes/api'), 9 | DB = require('./accessDB'), 10 | protectJSON = require('./lib/protectJSON'), 11 | app = express(); 12 | 13 | app.set('views', __dirname + '/views'); 14 | app.set('view engine', 'pug'); 15 | app.use(session({ 16 | secret: 'customermanagerstandard', 17 | saveUninitialized: true, 18 | resave: true })); 19 | app.use(cookieParser()); 20 | app.use(bodyParser.urlencoded({ extended: true })); 21 | app.use(bodyParser.json()); 22 | app.use(express.static(__dirname + '/../')); 23 | app.use(errorhandler()); 24 | app.use(protectJSON); 25 | app.use(csrf()); 26 | 27 | app.use(function (req, res, next) { 28 | var csrf = req.csrfToken(); 29 | res.cookie('XSRF-TOKEN', csrf); 30 | res.locals._csrf = csrf; 31 | next(); 32 | }) 33 | 34 | process.on('uncaughtException', function (err) { 35 | if (err) console.log(err, err.stack); 36 | }); 37 | 38 | //Local Connection 39 | var conn = 'mongodb://localhost/customermanager'; 40 | var db = new DB.startup(conn); 41 | 42 | // Routes 43 | app.get('/', routes.index); 44 | 45 | // JSON API 46 | var baseUrl = '/api/dataservice/'; 47 | 48 | app.get(baseUrl + 'Customers', api.customers); 49 | app.get(baseUrl + 'Customer/:id', api.customer); 50 | app.get(baseUrl + 'CustomersSummary', api.customersSummary); 51 | app.get(baseUrl + 'CustomerById/:id', api.customer); 52 | 53 | app.post(baseUrl + 'PostCustomer', api.addCustomer); 54 | app.put(baseUrl + 'PutCustomer/:id', api.editCustomer); 55 | app.delete(baseUrl + 'DeleteCustomer/:id', api.deleteCustomer); 56 | 57 | app.get(baseUrl + 'States', api.states); 58 | 59 | app.get(baseUrl + 'CheckUnique/:id', api.checkUnique); 60 | 61 | app.post(baseUrl + 'Login', api.login); 62 | app.post(baseUrl + 'Logout', api.logout); 63 | 64 | 65 | // redirect all others to the index (HTML5 history) 66 | app.get('*', routes.index); 67 | 68 | // Start server 69 | 70 | app.listen(3000, function () { 71 | console.log("CustMgr Express server listening on port %d in %s mode", this.address().port, app.settings.env); 72 | }); 73 | -------------------------------------------------------------------------------- /Src/CustomerManager/server/views/index.jade: -------------------------------------------------------------------------------- 1 | include ../../index.html 2 | -------------------------------------------------------------------------------- /Src/CustomerManager/test/karma.conf.js: -------------------------------------------------------------------------------- 1 | module.exports = function (config) { 2 | config.set({ 3 | basePath: '../', 4 | port: 9876, 5 | frameworks: ['jasmine'], 6 | files: [ 7 | //Library scripts 8 | 'test/lib/angular.js', //Ensure Angular is loaded first, 9 | 'test/lib/breeze.min.js', //Ensure Angular is loaded first 10 | 'test/lib/*.js', 11 | 'Scripts/**/*.js', 12 | 13 | //App and test scripts (order matters!) 14 | 'test/helpers/*.js', 15 | 'app/wc.directives/directives/wcOverlay.js', 16 | 'app/wc.directives/directives/menuHighlighter.js', 17 | 'app/customersApp/app.js', 18 | 'app/customersApp/**/*.js', 19 | 'test/unit/*.js' 20 | ], 21 | autoWatch: true, 22 | browsers: ['Chrome'], 23 | reporters: ['progress'] 24 | }); 25 | }; 26 | 27 | -------------------------------------------------------------------------------- /Src/CustomerManager/test/unit/customersServiceSpec.js: -------------------------------------------------------------------------------- 1 | describe('customersService Tests', function () { 2 | var httpBackend, 3 | serviceUrl = '/api/dataservice/customersSummary?$top=10&$skip=0', 4 | custs = [{ 5 | "id": 1, 6 | "firstName": "Marcus", 7 | "lastName": "HighTower", 8 | "city": "Phoenix", 9 | "state": { 10 | "id": 1, 11 | "abbreviation": "AZ", 12 | "name": " Arizona" 13 | }, 14 | "orderCount": 6, 15 | "gender": "Male" 16 | }]; 17 | 18 | beforeEach(function () { 19 | module('customersApp'); 20 | 21 | inject(function ($httpBackend) { 22 | httpBackend = $httpBackend; 23 | }); 24 | }); 25 | 26 | //Ensure no expectations were missed (expectGET or expectPOST) 27 | afterEach(function () { 28 | httpBackend.verifyNoOutstandingExpectation(); 29 | httpBackend.verifyNoOutstandingRequest(); 30 | }); 31 | 32 | it('customersService should return custom object', function () { 33 | inject(function (customersService) { 34 | var response = { 35 | totalRecords: 1, 36 | results: custs 37 | }; 38 | //Header normally sent from server and contains the totalRecords 39 | httpBackend.when('GET', serviceUrl).respond(custs, { 'X-InlineCount': '1' }); 40 | 41 | var test = { 42 | handler: function () { } 43 | }; 44 | 45 | //Monitor the handler function 46 | spyOn(test, 'handler'); 47 | 48 | customersService.getCustomersSummary(0, 10).then(test.handler); 49 | httpBackend.flush(); 50 | 51 | //Ensure handler function received proper response data 52 | expect(test.handler).toHaveBeenCalledWith(response); 53 | }); 54 | }); 55 | 56 | it('customersService should return custom object with totalRecords equal to 1', function () { 57 | inject(function (customersService) { 58 | //Header normally sent from server and contains the totalRecords 59 | httpBackend.when('GET', serviceUrl).respond(custs, { 'X-InlineCount': '1' }); 60 | customersService.getCustomersSummary(0, 10).then(function (result) { 61 | expect(result.totalRecords).toEqual(1); 62 | }); 63 | httpBackend.flush(); 64 | }); 65 | }); 66 | 67 | }); -------------------------------------------------------------------------------- /Src/CustomerManager/test/unit/wcOverlaySpec.js: -------------------------------------------------------------------------------- 1 | describe('wcOverlay directive specs', function () { 2 | var scope, compile, element, compiledOverlay; 3 | 4 | beforeEach(module('wc.directives')); 5 | 6 | beforeEach(inject(function ($rootScope, $compile) { 7 | scope = $rootScope; 8 | compile = $compile; 9 | 10 | element = angular.element("

    Loading...
    "); 11 | 12 | scope.delayTime = 100; 13 | 14 | compiledOverlay = compile(element)(scope); 15 | })); 16 | 17 | it('Should have appended the directive template', function () { 18 | expect(compiledOverlay.find('div').hasClass('overlayContainer')).toBe(true); 19 | }); 20 | 21 | }); -------------------------------------------------------------------------------- /Src/LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 Dan Wahlin and Wahlin Consulting (http://github.com/DanWahlin) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /copyFolders.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var fse = require('fs-extra'), 4 | ignoreDirs = ['Creating a Module Factory Controller and View', 5 | 'Unit Testing AngularJS Components', 6 | 'Working with Controllers and Watches']; 7 | 8 | function copyDirectory(srcDir, startDir, copyToSubFolderName) { 9 | 10 | //Iterate through directories 11 | fse.readdirSync(startDir).forEach(function (dir) { 12 | var directory = startDir + '/' + dir, 13 | stat = fse.lstatSync(directory); 14 | 15 | if (stat.isDirectory()) { 16 | if (ignoreDirs.indexOf(dir) === -1) { //Make sure the ignoreDirs aren't involved in the copy operations 17 | var targetDir = directory + '/' + copyToSubFolderName, //Target directory src should be copied to 18 | filesOverlaySrc = directory + '/Files', //If no srcDir is provided then we're overlaying lab files into the targetDir 19 | finalSrc = (srcDir) ? srcDir : filesOverlaySrc; 20 | 21 | fse.copySync(finalSrc, targetDir); 22 | console.log('Copied ' + finalSrc + ' to ' + targetDir); 23 | } 24 | } 25 | }); 26 | } 27 | 28 | //Copy src into Begin folder of each lab 29 | copyDirectory('./Src', './Labs', 'Begin'); 30 | 31 | //Copy Files into Begin folder of each lab 32 | copyDirectory(null, './Labs', 'Begin'); -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "foldercopier", 3 | "version": "1.0.0", 4 | "description": "Copies source code from destination folder into lab folders and overlays specific lab files.", 5 | "author": "Dan Wahlin", 6 | "main": "copyFolders.js", 7 | "dependencies": { 8 | "fs-extra": "^2.1.2" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | To build the labs do the following: 2 | 3 | 4 | 1. Download the code and extract it to your machine (or use git). 5 | 2. Run "npm install" from a command prompt at the root of the folder. 6 | 3. Run "node copyFolders.js" to generate the lab code output. 7 | --------------------------------------------------------------------------------