|
|
@@ -8,11 +8,9 @@ window.addEventListener('hashchange', function () {
|
|
|
Seed.broadcast('filterchange')
|
|
|
})
|
|
|
|
|
|
-Seed.controller('todos', {
|
|
|
+var Todos = Seed.ViewModel.extend({
|
|
|
|
|
|
- // initializer, reserved
|
|
|
- init: function () {
|
|
|
- window.app = this
|
|
|
+ initialize: function () {
|
|
|
// listen for hashtag change
|
|
|
this.updateFilter()
|
|
|
this.$on('filterchange', this.updateFilter.bind(this))
|
|
|
@@ -21,88 +19,91 @@ Seed.controller('todos', {
|
|
|
this.remaining = this.todos.filter(filters.active).length
|
|
|
},
|
|
|
|
|
|
- // computed properties ----------------------------------------------------
|
|
|
- total: {get: function () {
|
|
|
- return this.todos.length
|
|
|
- }},
|
|
|
-
|
|
|
- completed: {get: function () {
|
|
|
- return this.total - this.remaining
|
|
|
- }},
|
|
|
-
|
|
|
- // dynamic context computed property using info from target viewmodel
|
|
|
- todoFiltered: {get: function (ctx) {
|
|
|
- return filters[this.filter]({ completed: ctx.vm.completed })
|
|
|
- }},
|
|
|
-
|
|
|
- // dynamic context computed property using info from target element
|
|
|
- filterSelected: {get: function (ctx) {
|
|
|
- return this.filter === ctx.el.textContent.toLowerCase()
|
|
|
- }},
|
|
|
-
|
|
|
- // two-way computed property with both getter and setter
|
|
|
- allDone: {
|
|
|
- get: function () {
|
|
|
- return this.remaining === 0
|
|
|
+ properties: {
|
|
|
+
|
|
|
+ updateFilter: function () {
|
|
|
+ var filter = location.hash.slice(2)
|
|
|
+ this.filter = (filter in filters) ? filter : 'all'
|
|
|
},
|
|
|
- set: function (value) {
|
|
|
- this.todos.forEach(function (todo) {
|
|
|
- todo.completed = value
|
|
|
- })
|
|
|
- this.remaining = value ? 0 : this.total
|
|
|
- todoStorage.save(this.todos)
|
|
|
- }
|
|
|
- },
|
|
|
|
|
|
- // event handlers ---------------------------------------------------------
|
|
|
- addTodo: function () {
|
|
|
- var value = this.newTodo && this.newTodo.trim()
|
|
|
- if (value) {
|
|
|
- this.todos.unshift({ title: value, completed: false })
|
|
|
- this.newTodo = ''
|
|
|
- this.remaining++
|
|
|
- todoStorage.save(this.todos)
|
|
|
- }
|
|
|
- },
|
|
|
+ // computed properties ----------------------------------------------------
|
|
|
+ total: {get: function () {
|
|
|
+ return this.todos.length
|
|
|
+ }},
|
|
|
+
|
|
|
+ completed: {get: function () {
|
|
|
+ return this.total - this.remaining
|
|
|
+ }},
|
|
|
+
|
|
|
+ // dynamic context computed property using info from target viewmodel
|
|
|
+ todoFiltered: {get: function (ctx) {
|
|
|
+ return filters[this.filter]({ completed: ctx.vm.completed })
|
|
|
+ }},
|
|
|
+
|
|
|
+ // dynamic context computed property using info from target element
|
|
|
+ filterSelected: {get: function (ctx) {
|
|
|
+ return this.filter === ctx.el.textContent.toLowerCase()
|
|
|
+ }},
|
|
|
+
|
|
|
+ // two-way computed property with both getter and setter
|
|
|
+ allDone: {
|
|
|
+ get: function () {
|
|
|
+ return this.remaining === 0
|
|
|
+ },
|
|
|
+ set: function (value) {
|
|
|
+ this.todos.forEach(function (todo) {
|
|
|
+ todo.completed = value
|
|
|
+ })
|
|
|
+ this.remaining = value ? 0 : this.total
|
|
|
+ todoStorage.save(this.todos)
|
|
|
+ }
|
|
|
+ },
|
|
|
|
|
|
- removeTodo: function (e) {
|
|
|
- this.todos.remove(e.vm)
|
|
|
- this.remaining -= e.vm.completed ? 0 : 1
|
|
|
- todoStorage.save(this.todos)
|
|
|
- },
|
|
|
+ // event handlers ---------------------------------------------------------
|
|
|
+ addTodo: function () {
|
|
|
+ var value = this.newTodo && this.newTodo.trim()
|
|
|
+ if (value) {
|
|
|
+ this.todos.unshift({ title: value, completed: false })
|
|
|
+ this.newTodo = ''
|
|
|
+ this.remaining++
|
|
|
+ todoStorage.save(this.todos)
|
|
|
+ }
|
|
|
+ },
|
|
|
|
|
|
- toggleTodo: function (e) {
|
|
|
- this.remaining += e.vm.completed ? -1 : 1
|
|
|
- todoStorage.save(this.todos)
|
|
|
- },
|
|
|
+ removeTodo: function (e) {
|
|
|
+ this.todos.remove(e.vm)
|
|
|
+ this.remaining -= e.vm.completed ? 0 : 1
|
|
|
+ todoStorage.save(this.todos)
|
|
|
+ },
|
|
|
|
|
|
- editTodo: function (e) {
|
|
|
- this.beforeEditCache = e.vm.title
|
|
|
- e.vm.editing = true
|
|
|
- },
|
|
|
+ toggleTodo: function (e) {
|
|
|
+ this.remaining += e.vm.completed ? -1 : 1
|
|
|
+ todoStorage.save(this.todos)
|
|
|
+ },
|
|
|
|
|
|
- doneEdit: function (e) {
|
|
|
- if (!e.vm.editing) return
|
|
|
- e.vm.editing = false
|
|
|
- e.vm.title = e.vm.title.trim()
|
|
|
- if (!e.vm.title) this.removeTodo(e)
|
|
|
- todoStorage.save(this.todos)
|
|
|
- },
|
|
|
+ editTodo: function (e) {
|
|
|
+ this.beforeEditCache = e.vm.title
|
|
|
+ e.vm.editing = true
|
|
|
+ },
|
|
|
|
|
|
- cancelEdit: function (e) {
|
|
|
- e.vm.editing = false
|
|
|
- e.vm.title = this.beforeEditCache
|
|
|
- },
|
|
|
+ doneEdit: function (e) {
|
|
|
+ if (!e.vm.editing) return
|
|
|
+ e.vm.editing = false
|
|
|
+ e.vm.title = e.vm.title.trim()
|
|
|
+ if (!e.vm.title) this.removeTodo(e)
|
|
|
+ todoStorage.save(this.todos)
|
|
|
+ },
|
|
|
|
|
|
- removeCompleted: function () {
|
|
|
- this.todos = this.todos.filter(filters.active)
|
|
|
- todoStorage.save(this.todos)
|
|
|
- },
|
|
|
+ cancelEdit: function (e) {
|
|
|
+ e.vm.editing = false
|
|
|
+ e.vm.title = this.beforeEditCache
|
|
|
+ },
|
|
|
|
|
|
- updateFilter: function () {
|
|
|
- var filter = location.hash.slice(2)
|
|
|
- this.filter = (filter in filters) ? filter : 'all'
|
|
|
+ removeCompleted: function () {
|
|
|
+ this.todos = this.todos.filter(filters.active)
|
|
|
+ todoStorage.save(this.todos)
|
|
|
+ }
|
|
|
}
|
|
|
})
|
|
|
|
|
|
-Seed.bootstrap()
|
|
|
+var app = new Todos({ el: '#todoapp' })
|