diff options
Diffstat (limited to 'third_party/webkit/PerformanceTests/Speedometer/resources/todomvc/architecture-examples/angularjs/js')
5 files changed, 298 insertions, 0 deletions
diff --git a/third_party/webkit/PerformanceTests/Speedometer/resources/todomvc/architecture-examples/angularjs/js/app.js b/third_party/webkit/PerformanceTests/Speedometer/resources/todomvc/architecture-examples/angularjs/js/app.js new file mode 100644 index 0000000000..5f30ea3a11 --- /dev/null +++ b/third_party/webkit/PerformanceTests/Speedometer/resources/todomvc/architecture-examples/angularjs/js/app.js @@ -0,0 +1,32 @@ +/*global angular */ + +/** + * The main TodoMVC app module + * + * @type {angular.Module} + */ +angular.module('todomvc', ['ngRoute', 'ngResource']) + .config(function ($routeProvider) { + 'use strict'; + + 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('/', routeConfig) + .when('/:status', routeConfig) + .otherwise({ + redirectTo: '/' + }); + }); diff --git a/third_party/webkit/PerformanceTests/Speedometer/resources/todomvc/architecture-examples/angularjs/js/controllers/todoCtrl.js b/third_party/webkit/PerformanceTests/Speedometer/resources/todomvc/architecture-examples/angularjs/js/controllers/todoCtrl.js new file mode 100644 index 0000000000..a39d5aec8c --- /dev/null +++ b/third_party/webkit/PerformanceTests/Speedometer/resources/todomvc/architecture-examples/angularjs/js/controllers/todoCtrl.js @@ -0,0 +1,126 @@ +/*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.status = ''; + + $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 } : {}; + }); + + $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) { + $scope.editedTodo = null; + 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); + } + }); + }; + }); diff --git a/third_party/webkit/PerformanceTests/Speedometer/resources/todomvc/architecture-examples/angularjs/js/directives/todoEscape.js b/third_party/webkit/PerformanceTests/Speedometer/resources/todomvc/architecture-examples/angularjs/js/directives/todoEscape.js new file mode 100644 index 0000000000..944b52c5f3 --- /dev/null +++ b/third_party/webkit/PerformanceTests/Speedometer/resources/todomvc/architecture-examples/angularjs/js/directives/todoEscape.js @@ -0,0 +1,24 @@ +/*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); + } + }); + + scope.$on('$destroy', function () { + elem.unbind('keydown'); + }); + }; + }); diff --git a/third_party/webkit/PerformanceTests/Speedometer/resources/todomvc/architecture-examples/angularjs/js/directives/todoFocus.js b/third_party/webkit/PerformanceTests/Speedometer/resources/todomvc/architecture-examples/angularjs/js/directives/todoFocus.js new file mode 100644 index 0000000000..e1e6c21c90 --- /dev/null +++ b/third_party/webkit/PerformanceTests/Speedometer/resources/todomvc/architecture-examples/angularjs/js/directives/todoFocus.js @@ -0,0 +1,20 @@ +/*global angular */ + +/** + * Directive that places focus on the element it is applied to when the + * expression it binds to evaluates to true + */ +angular.module('todomvc') + .directive('todoFocus', function todoFocus($timeout) { + 'use strict'; + + return function (scope, elem, attrs) { + scope.$watch(attrs.todoFocus, function (newVal) { + if (newVal) { + $timeout(function () { + elem[0].focus(); + }, 0, false); + } + }); + }; + }); diff --git a/third_party/webkit/PerformanceTests/Speedometer/resources/todomvc/architecture-examples/angularjs/js/services/todoStorage.js b/third_party/webkit/PerformanceTests/Speedometer/resources/todomvc/architecture-examples/angularjs/js/services/todoStorage.js new file mode 100644 index 0000000000..b68e59628d --- /dev/null +++ b/third_party/webkit/PerformanceTests/Speedometer/resources/todomvc/architecture-examples/angularjs/js/services/todoStorage.js @@ -0,0 +1,96 @@ +/*global angular */ + +/** + * Services that persists and retrieves todos from memory or a backend API + * if available. + * + * They both follow the same API, returning promises for all changes to the + * model. + */ +angular.module('todomvc') + .factory('todoStorage', function ($http, $injector) { + 'use strict'; + return Promise.resolve().then(function() { + return $injector.get('localCache'); + }); + }) + + .factory('localCache', function ($q) { + 'use strict'; + + var STORAGE_ID = 'todos-angularjs'; + + var store = { + todos: [], + cache: [], + + _getFromLocalCache: function () { + // return JSON.parse(this.cache[STORAGE_ID] || '[]'); + return []; + }, + + _saveToLocalCache: function (todos) { + // this.cache[STORAGE_ID] = JSON.stringify(todos); + return; + }, + + clearCompleted: function () { + var deferred = $q.defer(); + + var incompleteTodos = store.todos.filter(function (todo) { + return !todo.completed; + }); + + angular.copy(incompleteTodos, store.todos); + + store._saveToLocalCache(store.todos); + deferred.resolve(store.todos); + + return deferred.promise; + }, + + delete: function (todo) { + var deferred = $q.defer(); + + store.todos.splice(store.todos.indexOf(todo), 1); + + store._saveToLocalCache(store.todos); + deferred.resolve(store.todos); + + return deferred.promise; + }, + + get: function () { + var deferred = $q.defer(); + + angular.copy(store._getFromLocalCache(), store.todos); + deferred.resolve(store.todos); + + return deferred.promise; + }, + + insert: function (todo) { + var deferred = $q.defer(); + + store.todos.push(todo); + + store._saveToLocalCache(store.todos); + deferred.resolve(store.todos); + + return deferred.promise; + }, + + put: function (todo, index) { + var deferred = $q.defer(); + + store.todos[index] = todo; + + store._saveToLocalCache(store.todos); + deferred.resolve(store.todos); + + return deferred.promise; + } + }; + + return store; + }); |