Skip to content

Commit

Permalink
Start seeing the todo...
Browse files Browse the repository at this point in the history
  • Loading branch information
amitaibu committed Nov 22, 2014
1 parent 19b27c5 commit f3b52b0
Show file tree
Hide file tree
Showing 12 changed files with 437 additions and 102 deletions.
4 changes: 2 additions & 2 deletions client/Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -391,7 +391,7 @@ module.exports = function (grunt) {
options: {
space: ' ',
wrap: '"use strict";\n\n {%= __ngModule %}',
name: 'config',
name: 'config'
},
// Environment targets
development: {
Expand All @@ -405,7 +405,7 @@ module.exports = function (grunt) {
}
}
},
traivs: {
travis: {
options: {
dest: '<%= yeoman.app %>/scripts/config.js'
},
Expand Down
111 changes: 61 additions & 50 deletions client/app/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,42 +14,66 @@
<!-- build:css(.tmp) styles/main.css -->
<link rel="stylesheet" href="styles/main.css">
<!-- endbuild -->
<style>[ng-cloak] { display: none; }</style>
</head>
<body ng-app="clientApp">
<!--[if lt IE 7]>
<p class="browsehappy">You are using an <strong>outdated</strong> browser. Please <a href="http://browsehappy.com/">upgrade your browser</a> to improve your experience.</p>
<![endif]-->

<!-- Add your site or application content here -->
<div class="container">
<div class="header">
<ul class="nav nav-pills pull-right">
<li class="active"><a ng-href="#">Home</a></li>
<li><a ng-href="#/about">About</a></li>
<li><a ng-href="#">Contact</a></li>
</ul>
<h3 class="text-muted">client</h3>
</div>

<div ng-view=""></div>

<div class="footer">
<p><span class="glyphicon glyphicon-heart"></span> from the Yeoman team</p>
</div>
</div>
<body ng-app="todomvc">
<ng-view />


<!-- Google Analytics: change UA-XXXXX-X to be your site's ID -->
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');

ga('create', 'UA-XXXXX-X');
ga('send', 'pageview');
<script type="text/ng-template" id="todomvc-index.html">
<section id="todoapp">
<header id="header">
<h1>todos</h1>
<form id="todo-form" ng-submit="addTodo()">
<input id="new-todo" placeholder="What needs to be done?" ng-model="newTodo" ng-disabled="saving" autofocus>
</form>
</header>
<section id="main" ng-show="todos.length" ng-cloak>
<input id="toggle-all" type="checkbox" ng-model="allChecked" ng-click="markAll(allChecked)">
<label for="toggle-all">Mark all as complete</label>
<ul id="todo-list">
<li ng-repeat="todo in todos | filter:statusFilter track by $index" ng-class="{completed: todo.completed, editing: todo == editedTodo}">
<div class="view">
<input class="toggle" type="checkbox" ng-model="todo.completed" ng-change="toggleCompleted(todo)">
<label ng-dblclick="editTodo(todo)">{{todo.title}}</label>
<button class="destroy" ng-click="removeTodo(todo)"></button>
</div>
<form ng-submit="saveEdits(todo, 'submit')">
<input class="edit" ng-trim="false" ng-model="todo.title" todo-escape="revertEdits(todo)" ng-blur="saveEdits(todo, 'blur')" todo-focus="todo == editedTodo">
</form>
</li>
</ul>
</section>
<footer id="footer" ng-show="todos.length" ng-cloak>
<span id="todo-count"><strong>{{remainingCount}}</strong>
<ng-pluralize count="remainingCount" when="{ one: 'item left', other: 'items left' }"></ng-pluralize>
</span>
<ul id="filters">
<li>
<a ng-class="{selected: status == ''} " href="#/">All</a>
</li>
<li>
<a ng-class="{selected: status == 'active'}" href="#/active">Active</a>
</li>
<li>
<a ng-class="{selected: status == 'completed'}" href="#/completed">Completed</a>
</li>
</ul>
<button id="clear-completed" ng-click="clearCompletedTodos()" ng-show="completedCount">Clear completed ({{completedCount}})</button>
</footer>
</section>
<footer id="info">
<p>Double-click to edit a todo</p>
<p>Credits:
<a href="http://twitter.com/cburgdorf">Christoph Burgdorf</a>,
<a href="http://ericbidelman.com">Eric Bidelman</a>,
<a href="http://jacobmumm.com">Jacob Mumm</a> and
<a href="http://igorminar.com">Igor Minar</a>
</p>
<p>Part of <a href="http://todomvc.com">TodoMVC</a></p>
</footer>
</script>


<!-- build:js(.) scripts/oldieshim.js -->
<!--[if lt IE 9]>
<script src="bower_components/es5-shim/es5-shim.js"></script>
Expand All @@ -59,32 +83,19 @@ <h3 class="text-muted">client</h3>

<!-- build:js(.) scripts/vendor.js -->
<!-- bower:js -->
<script src="bower_components/jquery/dist/jquery.js"></script>
<script src="bower_components/angular/angular.js"></script>
<script src="bower_components/bootstrap-sass-official/assets/javascripts/bootstrap/affix.js"></script>
<script src="bower_components/bootstrap-sass-official/assets/javascripts/bootstrap/alert.js"></script>
<script src="bower_components/bootstrap-sass-official/assets/javascripts/bootstrap/button.js"></script>
<script src="bower_components/bootstrap-sass-official/assets/javascripts/bootstrap/carousel.js"></script>
<script src="bower_components/bootstrap-sass-official/assets/javascripts/bootstrap/collapse.js"></script>
<script src="bower_components/bootstrap-sass-official/assets/javascripts/bootstrap/dropdown.js"></script>
<script src="bower_components/bootstrap-sass-official/assets/javascripts/bootstrap/tab.js"></script>
<script src="bower_components/bootstrap-sass-official/assets/javascripts/bootstrap/transition.js"></script>
<script src="bower_components/bootstrap-sass-official/assets/javascripts/bootstrap/scrollspy.js"></script>
<script src="bower_components/bootstrap-sass-official/assets/javascripts/bootstrap/modal.js"></script>
<script src="bower_components/bootstrap-sass-official/assets/javascripts/bootstrap/tooltip.js"></script>
<script src="bower_components/bootstrap-sass-official/assets/javascripts/bootstrap/popover.js"></script>
<script src="bower_components/angular-route/angular-route.js"></script>
<script src="bower_components/todomvc-common/base.js"></script>
<script src="bower_components/lodash/dist/lodash.compat.js"></script>
<script src="bower_components/restangular/dist/restangular.js"></script>
<!-- endbower -->
<!-- endbuild -->

<!-- build:js({.tmp,app}) scripts/scripts.js -->
<script src="scripts/app.js"></script>
<script src="scripts/config.js" />
<script src="scripts/controllers/main.js"></script>
<script src="scripts/controllers/about.js"></script>
<script src="scripts/config.js"></script>
<script src="scripts/controllers/todoCtrl.js"></script>
<script src="scripts/directives/todoEscape.js"></script>
<script src="scripts/directives/todoFocus.js"></script>
<script src="scripts/services/todoStorage.js"></script>
<!-- endbuild -->
</body>
</html>
33 changes: 22 additions & 11 deletions client/app/scripts/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,39 @@

/**
* @ngdoc overview
* @name clientApp
* @name todomvc
* @description
* # clientApp
* # todomvc
*
* Main module of the application.
*/
angular
.module('clientApp', [
.module('todomvc', [
'ngRoute',
'config'
])
.config(function ($routeProvider) {
var routeConfig = {
controller: 'TodoCtrl',
templateUrl: 'todomvc-index.html',
resolve: {
store: function (todoStorage) {
// Get the correct module (API or localStorage).
return todoStorage.then(function (module) {
module.get(); // Fetch the todo records in the background.
return module;
});
}
}
};

$routeProvider
.when('/', {
templateUrl: 'views/main.html',
controller: 'MainCtrl'
})
.when('/about', {
templateUrl: 'views/about.html',
controller: 'AboutCtrl'
})
.when('/', routeConfig)
.when('/:status', routeConfig)
.otherwise({
redirectTo: '/'
});

});


17 changes: 0 additions & 17 deletions client/app/scripts/controllers/about.js

This file was deleted.

17 changes: 0 additions & 17 deletions client/app/scripts/controllers/main.js

This file was deleted.

125 changes: 125 additions & 0 deletions client/app/scripts/controllers/todoCtrl.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
/*global angular */

/**
* The main controller for the app. The controller:
* - retrieves and persists the model via the todoStorage service
* - exposes the model to the template and provides event handlers
*/
angular.module('todomvc')
.controller('TodoCtrl', function TodoCtrl($scope, $routeParams, $filter, store) {
'use strict';

var todos = $scope.todos = store.todos;

$scope.newTodo = '';
$scope.editedTodo = null;

$scope.$watch('todos', function () {
$scope.remainingCount = $filter('filter')(todos, { completed: false }).length;
$scope.completedCount = todos.length - $scope.remainingCount;
$scope.allChecked = !$scope.remainingCount;
}, true);

// Monitor the current route for changes and adjust the filter accordingly.
$scope.$on('$routeChangeSuccess', function () {
var status = $scope.status = $routeParams.status || '';

$scope.statusFilter = (status === 'active') ?
{ completed: false } : (status === 'completed') ?
{ completed: true } : null;
});

$scope.addTodo = function () {
var newTodo = {
title: $scope.newTodo.trim(),
completed: false
};

if (!newTodo.title) {
return;
}

$scope.saving = true;
store.insert(newTodo)
.then(function success() {
$scope.newTodo = '';
})
.finally(function () {
$scope.saving = false;
});
};

$scope.editTodo = function (todo) {
$scope.editedTodo = todo;
// Clone the original todo to restore it on demand.
$scope.originalTodo = angular.extend({}, todo);
};

$scope.saveEdits = function (todo, event) {
// Blur events are automatically triggered after the form submit event.
// This does some unfortunate logic handling to prevent saving twice.
if (event === 'blur' && $scope.saveEvent === 'submit') {
$scope.saveEvent = null;
return;
}

$scope.saveEvent = event;

if ($scope.reverted) {
// Todo edits were reverted-- don't save.
$scope.reverted = null;
return;
}

todo.title = todo.title.trim();

if (todo.title === $scope.originalTodo.title) {
return;
}

store[todo.title ? 'put' : 'delete'](todo)
.then(function success() {}, function error() {
todo.title = $scope.originalTodo.title;
})
.finally(function () {
$scope.editedTodo = null;
});
};

$scope.revertEdits = function (todo) {
todos[todos.indexOf(todo)] = $scope.originalTodo;
$scope.editedTodo = null;
$scope.originalTodo = null;
$scope.reverted = true;
};

$scope.removeTodo = function (todo) {
store.delete(todo);
};

$scope.saveTodo = function (todo) {
store.put(todo);
};

$scope.toggleCompleted = function (todo, completed) {
if (angular.isDefined(completed)) {
todo.completed = completed;
}
store.put(todo, todos.indexOf(todo))
.then(function success() {}, function error() {
todo.completed = !todo.completed;
});
};

$scope.clearCompletedTodos = function () {
store.clearCompleted();
};

$scope.markAll = function (completed) {
todos.forEach(function (todo) {
if (todo.completed !== completed) {
$scope.toggleCompleted(todo, completed);
}
});
};
});
20 changes: 20 additions & 0 deletions client/app/scripts/directives/todoEscape.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*global angular */

/**
* Directive that executes an expression when the element it is applied to gets
* an `escape` keydown event.
*/
angular.module('todomvc')
.directive('todoEscape', function () {
'use strict';

var ESCAPE_KEY = 27;

return function (scope, elem, attrs) {
elem.bind('keydown', function (event) {
if (event.keyCode === ESCAPE_KEY) {
scope.$apply(attrs.todoEscape);
}
});
};
});
Loading

0 comments on commit f3b52b0

Please sign in to comment.