move defineProperty() into Binding, add setter for computed property

This commit is contained in:
Evan You 2013-08-09 12:18:34 -04:00
parent 75fc96a357
commit 52645e33bf
5 changed files with 50 additions and 39 deletions

View File

@ -5,3 +5,4 @@
- when a new object is set, recursively replace all properties with getter/setters that emit events.
- sd-with
- standarized way to reuse components (sd-component?)
- plugins: seed-touch, seed-storage, seed-router

View File

@ -28,9 +28,17 @@ Seed.controller('Todos', function (scope) {
return scope.remaining > 1 ? 'items' : 'item'
}}
scope.allDone = {get: function () {
scope.allDone = {
get: function () {
return scope.remaining === 0
}}
},
set: function (value) {
scope.todos.forEach(function (todo) {
todo.done = value
})
scope.remaining = value ? 0 : scope.total
}
}
// event handlers ---------------------------------------------------------
scope.addTodo = function (e) {
@ -62,13 +70,6 @@ Seed.controller('Todos', function (scope) {
scope.filter = e.el.dataset.filter
}
scope.toggleAll = function (e) {
scope.todos.forEach(function (todo) {
todo.done = e.el.checked
})
scope.remaining = e.el.checked ? 0 : scope.total
}
scope.removeCompleted = function () {
scope.todos = scope.todos.filter(function (todo) {
return !todo.done

View File

@ -25,8 +25,7 @@
<input
id="toggle-all"
type="checkbox"
sd-checked-oneway="allDone"
sd-on="change:toggleAll"
sd-checked="allDone"
>
<ul id="todo-list">
<!-- a single todo item -->

View File

@ -7,10 +7,14 @@ var Emitter = require('emitter')
* which has multiple directive instances on the DOM
* and multiple computed property dependents
*/
function Binding (value) {
this.value = value
function Binding (seed, key) {
this.seed = seed
this.key = key
this.set(seed.scope[key])
this.defineAccessors(seed, key)
this.instances = []
this.dependents = []
this.dependencies = []
}
/*
@ -21,7 +25,7 @@ Binding.prototype.set = function (value) {
self = this
// preprocess the value depending on its type
if (type === 'Object') {
if (value.get) { // computed property
if (value.get || value.set) { // computed property
self.isComputed = true
} else { // normal object
// TODO watchObject
@ -35,6 +39,29 @@ Binding.prototype.set = function (value) {
this.value = value
}
/*
* Define getter/setter for this binding on scope
*/
Binding.prototype.defineAccessors = function (seed, key) {
var self = this
Object.defineProperty(seed.scope, key, {
get: function () {
seed.emit('get', key)
return self.isComputed
? self.value.get()
: self.value
},
set: function (value) {
if (self.isComputed && self.value.set) {
self.value.set(value)
} else if (value !== self.value) {
self.value = value
self.update(value)
}
}
})
}
/*
* Process the value, then trigger updates on all dependents
*/

View File

@ -72,8 +72,12 @@ function Seed (el, options) {
}
// add event listener to update corresponding binding
// when a property is set
var self = this
this.on('get', function (key) {
if (parsingDeps) {
depsObserver.emit('get', self._bindings[key])
}
})
this.on('set', function (key, value) {
self._bindings[key].update(value)
})
@ -211,29 +215,9 @@ Seed.prototype._bind = function (directive) {
* Create binding and attach getter/setter for a key to the scope object
*/
Seed.prototype._createBinding = function (key) {
var binding = new Binding()
binding.set(this.scope[key])
var binding = new Binding(this, key)
this._bindings[key] = binding
if (binding.isComputed) this._computed.push(binding)
var seed = this
Object.defineProperty(this.scope, key, {
get: function () {
if (parsingDeps) {
depsObserver.emit('get', binding)
}
seed.emit('get', key)
return binding.isComputed
? binding.value.get()
: binding.value
},
set: function (value) {
if (value === binding.value) return
seed.emit('set', key, value)
}
})
return binding
}
@ -294,7 +278,6 @@ Seed.prototype._dump = function () {
* second pass in injectDeps()
*/
function parseDeps (binding) {
binding.dependencies = []
depsObserver.on('get', function (dep) {
binding.dependencies.push(dep)
})