app.js 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. /*global Vue, todoStorage */
  2. (function (exports) {
  3. 'use strict';
  4. exports.app = new Vue({
  5. // the root element that will be compiled
  6. el: '#todoapp',
  7. // data
  8. data: {
  9. todos: todoStorage.fetch(),
  10. newTodo: '',
  11. editedTodo: null
  12. },
  13. // a custom directive to wait for the DOM to be updated
  14. // before focusing on the input field.
  15. // http://vuejs.org/guide/directives.html#Writing_a_Custom_Directive
  16. directives: {
  17. 'todo-focus': function (value) {
  18. if (!value) {
  19. return;
  20. }
  21. var el = this.el;
  22. setTimeout(function () {
  23. el.focus();
  24. }, 0);
  25. }
  26. },
  27. // the `created` lifecycle hook.
  28. // this is where we do the initialization work.
  29. // http://vuejs.org/api/instantiation-options.html#created
  30. created: function () {
  31. // setup filters
  32. this.filters = {
  33. all: function (todo) {
  34. // collect dependency.
  35. // http://vuejs.org/guide/computed.html#Dependency_Collection_Gotcha
  36. /* jshint expr:true */
  37. todo.completed;
  38. return true;
  39. },
  40. active: function (todo) {
  41. return !todo.completed;
  42. },
  43. completed: function (todo) {
  44. return todo.completed;
  45. }
  46. };
  47. // default filter
  48. this.setFilter('all');
  49. },
  50. // computed property
  51. // http://vuejs.org/guide/computed.html
  52. computed: {
  53. remaining: function () {
  54. return this.todos.filter(this.filters.active).length
  55. },
  56. allDone: {
  57. $get: function () {
  58. return this.remaining === 0;
  59. },
  60. $set: function (value) {
  61. this.todos.forEach(function (todo) {
  62. todo.completed = value;
  63. });
  64. todoStorage.save();
  65. }
  66. }
  67. },
  68. // methods that implement data logic.
  69. // note there's no DOM manipulation here at all.
  70. methods: {
  71. setFilter: function (filter) {
  72. this.filter = filter;
  73. this.filterTodo = this.filters[filter];
  74. },
  75. addTodo: function () {
  76. var value = this.newTodo && this.newTodo.trim();
  77. if (!value) {
  78. return;
  79. }
  80. this.todos.push({ title: value, completed: false });
  81. this.newTodo = '';
  82. todoStorage.save();
  83. },
  84. removeTodo: function (todo) {
  85. this.todos.remove(todo.$data);
  86. todoStorage.save();
  87. },
  88. toggleTodo: function (todo) {
  89. todoStorage.save();
  90. },
  91. editTodo: function (todo) {
  92. this.beforeEditCache = todo.title;
  93. this.editedTodo = todo;
  94. },
  95. doneEdit: function (todo) {
  96. if (!this.editedTodo) {
  97. return;
  98. }
  99. this.editedTodo = null;
  100. todo.title = todo.title.trim();
  101. if (!todo.title) {
  102. this.removeTodo(todo);
  103. }
  104. todoStorage.save();
  105. },
  106. cancelEdit: function (todo) {
  107. this.editedTodo = null;
  108. todo.title = this.beforeEditCache;
  109. },
  110. removeCompleted: function () {
  111. this.todos.remove(function (todo) {
  112. return todo.completed;
  113. });
  114. todoStorage.save();
  115. }
  116. }
  117. });
  118. })(window);