app.js 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. seed.config({ debug: true })
  2. var filters = {
  3. all: function () { return true },
  4. active: function (todo) { return !todo.completed },
  5. completed: function (todo) { return todo.completed }
  6. }
  7. var todos = [
  8. {title: 'hi', completed: true},
  9. {title: 'ha', completed: false},
  10. {title: 'ho', completed: false},
  11. ]
  12. var Todos = seed.ViewModel.extend({
  13. init: function () {
  14. this.todos = todos//todoStorage.fetch()
  15. this.remaining = this.todos.filter(filters.active).length
  16. this.updateFilter()
  17. },
  18. props: {
  19. updateFilter: function () {
  20. var filter = location.hash.slice(2)
  21. this.filter = (filter in filters) ? filter : 'all'
  22. },
  23. // computed properties ----------------------------------------------------
  24. total: {get: function () {
  25. return this.todos.length
  26. }},
  27. completed: {get: function () {
  28. return this.total - this.remaining
  29. }},
  30. // dynamic context computed property using info from target viewmodel
  31. todoFiltered: {get: function (ctx) {
  32. return filters[this.filter]({ completed: ctx.vm.todo.completed })
  33. }},
  34. // dynamic context computed property using info from target element
  35. filterSelected: {get: function (ctx) {
  36. return this.filter === ctx.el.textContent.toLowerCase()
  37. }},
  38. // two-way computed property with both getter and setter
  39. allDone: {
  40. get: function () {
  41. return this.remaining === 0
  42. },
  43. set: function (value) {
  44. this.todos.forEach(function (todo) {
  45. todo.completed = value
  46. })
  47. this.remaining = value ? 0 : this.total
  48. todoStorage.save(this.todos)
  49. }
  50. },
  51. // event handlers ---------------------------------------------------------
  52. addTodo: function () {
  53. var value = this.newTodo && this.newTodo.trim()
  54. if (value) {
  55. this.todos.unshift({ title: value, completed: false })
  56. this.newTodo = ''
  57. this.remaining++
  58. todoStorage.save(this.todos)
  59. }
  60. },
  61. removeTodo: function (e) {
  62. this.todos.remove(e.item)
  63. this.remaining -= e.item.completed ? 0 : 1
  64. todoStorage.save(this.todos)
  65. },
  66. toggleTodo: function (e) {
  67. this.remaining += e.item.completed ? -1 : 1
  68. todoStorage.save(this.todos)
  69. },
  70. editTodo: function (e) {
  71. this.beforeEditCache = e.item.title
  72. e.item.editing = true
  73. },
  74. doneEdit: function (e) {
  75. if (!e.item.editing) return
  76. e.item.editing = false
  77. e.item.title = e.item.title.trim()
  78. if (!e.item.title) this.removeTodo(e)
  79. todoStorage.save(this.todos)
  80. },
  81. cancelEdit: function (e) {
  82. e.item.editing = false
  83. e.item.title = this.beforeEditCache
  84. },
  85. removeCompleted: function () {
  86. this.todos = this.todos.filter(filters.active)
  87. todoStorage.save(this.todos)
  88. }
  89. }
  90. })
  91. var app = new Todos({ el: '#todoapp' })
  92. window.addEventListener('hashchange', function () {
  93. app.updateFilter()
  94. })