├── .gitignore ├── Procfile ├── README.md ├── app.js ├── lib └── messageboard │ ├── index.js │ └── messageboard.js ├── package.json ├── public ├── index.html ├── scripts │ └── app │ │ ├── app.js │ │ └── messageboard.js └── views │ ├── greeting.html │ ├── home.html │ └── messageboard.html ├── routes ├── index.js └── messageboard.js ├── test ├── messageboard.js └── mocha.opts └── util ├── colorizedTerminal.js └── index.js /.gitignore: -------------------------------------------------------------------------------- 1 | .*.swp 2 | node_modules/ 3 | -------------------------------------------------------------------------------- /Procfile: -------------------------------------------------------------------------------- 1 | web: node app.js 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Angular Koans 2 | 3 | This project contains some koans for learning AngularJS. Using tags various practices are offered. 4 | 5 | ## Quick Start 6 | 7 | To start working on the first koan quickly, checkout the koan and read the description using the 8 | following commands. 9 | 10 | $ git checkout -b bootstrap-impl 01-bootstrap-angular 11 | $ git show --quiet 01-bootstrap-angular 12 | 13 | Read the description and get cracking at it. To move to the next koan checkout the `02-default-route` 14 | tag, then tag `3-greetings`, and so on. 15 | 16 | The remainder of this README describes how to run a koan and provides more details on the koan and 17 | solution tags provided by this repository. 18 | 19 | ## Running a Koan 20 | 21 | These koans are created using Node.js. If you haven't already make sure to install Node.js from 22 | [nodejs.org](http://nodejs.org/). Installation details are provided by Node.js. 23 | 24 | From any tag you can run the koans using the included server. First you need to install the required 25 | dependencies. 26 | 27 | $ npm install 28 | 29 | Then you can run the server. 30 | 31 | $ npm start 32 | 33 | ## Koans 34 | 35 | A list of koans is simply populated from the tags in this repository. These are annotated tags 36 | containing a description of the koan. 37 | 38 | To get a list of koans with a brief summary, you list the tags in the repository: 39 | 40 | $ git tag -ln1 41 | 42 | To read the full description of a koan, you show the full annotation of the commit. 43 | 44 | $ git show --quiet 45 | 46 | Note: this also includes the message of the commit that is marked by the tag. You can safely ignore 47 | this. 48 | 49 | For each koan two tags are provided. The first one marks the starting point of the koan. The second 50 | one marks the solution point in this repository. To start working on a koan you'd branch off the 51 | starting point. For example, to start with first koan you do create a solving branch and checkout 52 | that branch: 53 | 54 | $ git checkout -b bootstrap-impl 01-bootstrap-angular 55 | 56 | Tip: when you get stuck solving a koan you can consider reading the commit logs of the corresponding 57 | solution tag. These commit messages should be verbose on the changes. 58 | 59 | -------------------------------------------------------------------------------- /app.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | var express = require('express'), 4 | routes = require('./routes'), 5 | http = require('http'), 6 | terminal = require('./util'); 7 | 8 | function main(terminal) { 9 | var app = express(); 10 | app.set('port', process.env.PORT || 8080); 11 | app.use(express.static(__dirname + '/public')); 12 | app.get('/api/messageboard/list', routes.messageboard.list); 13 | http.createServer(app).listen(app.get('port'), function() { 14 | terminal.info("Server started on port: %s", app.get('port')); 15 | terminal.message("press CTRL-C to stop the server"); 16 | }); 17 | } 18 | 19 | main(terminal.colorized); 20 | 21 | -------------------------------------------------------------------------------- /lib/messageboard/index.js: -------------------------------------------------------------------------------- 1 | exports = module.exports = require('./messageboard'); 2 | -------------------------------------------------------------------------------- /lib/messageboard/messageboard.js: -------------------------------------------------------------------------------- 1 | var MessageBoard = { 2 | list: function() { 3 | return this.store.messages(); 4 | } 5 | } 6 | 7 | module.exports = MessageBoard 8 | 9 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular-examples", 3 | "version": "0.1.0", 4 | "author": "Bart Bakker ", 5 | "dependencies": { 6 | "express": "3.x", 7 | "colorize": "0.1.0" 8 | }, 9 | "devDependencies": { 10 | "should": "*", 11 | "sinon": "*", 12 | "mocha": "*" 13 | }, 14 | "engines": { 15 | "node": ">=0.10" 16 | }, 17 | "scripts": { 18 | "start": "node app.js", 19 | "test": "mocha" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Angular Koans 5 | 6 | 7 | 11 | 12 | 13 | 14 | 28 | 29 |
30 |
31 |
32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /public/scripts/app/app.js: -------------------------------------------------------------------------------- 1 | angular.module('koans', ['koans.messageboard']) 2 | .config(['$routeProvider', function($routeProvider) { 3 | $routeProvider.when('/home', { templateUrl: 'views/home.html' }) 4 | .when('/greeting', { templateUrl: 'views/greeting.html' }) 5 | .when('/messageboard', { templateUrl: 'views/messageboard.html', controller: 'MessageBoardController' }) 6 | .otherwise({redirectTo: '/home'}); 7 | }]) 8 | .run(['$rootScope', function($rootScope) { 9 | $rootScope.app = { 10 | name: 'Angular Koans' 11 | } 12 | }]) 13 | 14 | -------------------------------------------------------------------------------- /public/scripts/app/messageboard.js: -------------------------------------------------------------------------------- 1 | angular.module('koans.messageboard', []) 2 | .controller('MessageBoardController', ['$scope', 'MessageBoard', function($scope, messageBoard) { 3 | $scope.messages = messageBoard.messages(); 4 | }]) 5 | .factory('MessageBoard', ['$http', function($http) { 6 | return MessageBoard.create($http); 7 | }]); 8 | 9 | var MessageBoard = { 10 | create: function($http) { 11 | return Object.create(MessageBoard, { 12 | $http: { value: $http } 13 | }) 14 | }, 15 | 16 | messages: function() { 17 | return this.$http.get('/api/messageboard/list').then(function(response) { 18 | return response.data.map(MessageData.load) 19 | }); 20 | }, 21 | } 22 | 23 | var MessageData = { 24 | load: function(data) { 25 | return { id: data.id, 26 | text: data.message } 27 | } 28 | } 29 | 30 | -------------------------------------------------------------------------------- /public/views/greeting.html: -------------------------------------------------------------------------------- 1 |
2 |

Greetings, {{name || "Earthling"}}!

3 | 4 |
5 | 6 |
7 |
8 | -------------------------------------------------------------------------------- /public/views/home.html: -------------------------------------------------------------------------------- 1 | Home of the Angular Koans. 2 | 3 | -------------------------------------------------------------------------------- /public/views/messageboard.html: -------------------------------------------------------------------------------- 1 |
2 |

Message Board

3 |
    4 |
  • {{message.text}}
  • 5 |
6 |
7 | -------------------------------------------------------------------------------- /routes/index.js: -------------------------------------------------------------------------------- 1 | exports.messageboard = require('./messageboard.js'); 2 | -------------------------------------------------------------------------------- /routes/messageboard.js: -------------------------------------------------------------------------------- 1 | var MessageBoard = require('../lib/messageboard') 2 | 3 | var fixedMessageStore = { 4 | messages: function() { 5 | return [{id: 1, message: "Welcome to the message board"}, 6 | {id: 2, message: "You've round tripped to the server and back"}, 7 | {id: 3, message: "Well done!"}]; 8 | } 9 | } 10 | var messageBoard = Object.create(MessageBoard); 11 | messageBoard.store = fixedMessageStore; 12 | 13 | exports = module.exports = { 14 | list: function(req, res) { 15 | res.end(JSON.stringify(messageBoard.list())); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /test/messageboard.js: -------------------------------------------------------------------------------- 1 | var sinon = require('sinon') 2 | 3 | var MessageBoard = require('../lib/messageboard/messageboard.js') 4 | 5 | describe('message-board', function() { 6 | var subject 7 | var store 8 | 9 | beforeEach(function() { 10 | subject = Object.create(MessageBoard); 11 | subject.store = store = {}; 12 | }) 13 | 14 | it ('lists the messages are that posted on the board', function() { 15 | var messages = ['msg-1', 'msg-2']; 16 | store.messages = sinon.stub().returns(messages) 17 | subject.list().should.eql(messages) 18 | }) 19 | }) 20 | 21 | -------------------------------------------------------------------------------- /test/mocha.opts: -------------------------------------------------------------------------------- 1 | --require should 2 | --require sinon 3 | -------------------------------------------------------------------------------- /util/colorizedTerminal.js: -------------------------------------------------------------------------------- 1 | var colorize = require('colorize'), 2 | util = require('util'); 3 | 4 | var ColorizedTerminal = { 5 | info: function(message) { 6 | var args = Array.prototype.slice.call(arguments, 1).map( 7 | partial(this._colorize, 'cyan')); 8 | this._print(this._colorize('yellow', this._format(message, args))) 9 | }, 10 | 11 | message: function(text) { 12 | this._print(text) 13 | }, 14 | 15 | _print: function(text) { 16 | colorize.console.log(text) 17 | }, 18 | 19 | _format: function(message, args) { 20 | return util.format.apply(this, [message].concat(args)) 21 | }, 22 | 23 | _colorize: function(color, text) { 24 | return util.format('#%s[%s]', color, text) 25 | } 26 | } 27 | 28 | function partial(fn) { 29 | fixed_args = Array.prototype.slice.call(arguments, 1) 30 | return function() { 31 | dynamic_args = Array.prototype.slice.call(arguments) 32 | args = fixed_args.concat(dynamic_args) 33 | return fn.apply(null, args) 34 | } 35 | } 36 | 37 | exports = module.exports = ColorizedTerminal 38 | -------------------------------------------------------------------------------- /util/index.js: -------------------------------------------------------------------------------- 1 | exports = module.exports = { 2 | colorized: require('./colorizedTerminal') 3 | } 4 | --------------------------------------------------------------------------------