Skip to content

Commit

Permalink
added automatic depenencies
Browse files Browse the repository at this point in the history
  • Loading branch information
weepy committed Nov 15, 2012
1 parent e77e5d3 commit 02d3a37
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 47 deletions.
20 changes: 5 additions & 15 deletions README.md
@@ -1,7 +1,7 @@
attr
====

Evented Property getter/setter component
Evented Property getter/setter component and automatic dependency calculation

## API

Expand Down Expand Up @@ -66,9 +66,9 @@ name.on('change', function(new_name, old_name) {

These have the same API, except no setter and a function is passed in and is run to determine the intial value

### attr.computed(fn)
### attr.computed(fn, dependencies)

Creates a computed attr:
Creates a computed attr. If dependencies is not set explicitly, they are automatically calculated

```javascript
fullName = attr.computed(function() {
Expand All @@ -78,20 +78,10 @@ fullName = attr.computed(function() {
fullName() // => 'Homer Simpson'
```

### attr.depends()
### attr.depencencies

Returns the current dependencies
Contains the current dependencies

### attr.depends(array)

Set dependencies. attr is recalculated whenever a dependency changes

```javascript
fullName.depends([firstName, surName])
firstName('Bart')

fullName.value // => 'Bart Simpson'
```

# Testing

Expand Down
65 changes: 39 additions & 26 deletions index.js
Expand Up @@ -32,17 +32,22 @@ function extend(a, b) {
* simple attribute
*/

function createAttr(arg) {
var watcher = false

function Attr(arg) {

// IDEA: autocreate computed attr for function values
// if(typeof arg =='function') return createAttr.computed(arg)
// if(typeof arg =='function') return Attr.computed(arg)

function attr(v) {
if(arguments.length) {
// setter
attr.old = attr.value
attr.value = v

attr.emit('change', attr.value, attr.old)
} else {
if(watcher) watcher(attr)
}
return attr.value
}
Expand All @@ -56,11 +61,28 @@ function createAttr(arg) {
return attr
}



Attr.dependencies = function(fn) {
var deps = []
// watches for simple attr reads
watcher = function(attr) {
deps.push(attr)
}
var val = fn()
watcher = false
return {
value: val,
depends: deps
}
}


/*
* computed attribute
*/

createAttr.computed = function(fn) {
Attr.computed = function(fn, depends) {
function attr() {
// nb - there is no setter
attr.old = attr.value
Expand All @@ -72,36 +94,27 @@ createAttr.computed = function(fn) {
// mixin common methods
extend(attr, methods)

// set to initial value
attr.value = fn()

// setup dependencies
attr._depends = []

// dependency setter
attr.depends = function(deps) {
// getter
if(arguments.length == 0) return attr._depends

// unbind old
attr._depends.forEach(function(dep) {
dep.off('change', changeFn)
})

attr._depends = deps
// bind new
deps.forEach(function(dep) {
dep.on('change', changeFn)
})
return attr
if(depends) {
attr.value = fn() // set to initial value
} else {
var o = Attr.dependencies(fn)
depends = o.depends
attr.value = o.value
}

// static change function for binding
attr.depends = depends

depends.forEach(function(dep) {
dep.on('change', changeFn)
})

// static change function
function changeFn() {
attr.change()
}

return attr
}

module.exports = createAttr
module.exports = Attr
29 changes: 23 additions & 6 deletions test/test.attr.js
Expand Up @@ -136,20 +136,37 @@ describe('attr()', function(){

var fullName = attr.computed(function() {})

assert(fullName.depends().length == 0)
assert(fullName.depends.length == 0)
})

it('has 2 dependencies calculated automatically', function(){

var firstName = attr('John')
var surName = attr('Bob')

var fullName = attr.computed(function() { return firstName() + surName() })

assert(fullName.depends.length == 2)
})

it('has 1 dependencies when set explicitly', function(){

var firstName = attr('John')
var surName = attr('Bob')

var fullName = attr.computed(function() { return firstName() + surName() }, [firstName])

assert(fullName.depends.length == 1)
})

it('recalcs when a dependency changes', function(){

var firstName = attr('John')
it('recalcs when a dependency changes', function(){
var firstName = attr('John')
var surName = attr('Bob')

var fullName = attr.computed(function() {
return firstName() + ' ' + surName()
}).depends([surName, firstName])

assert(fullName._depends.length == 2)
})

surName('Sandy')

Expand Down

0 comments on commit 02d3a37

Please sign in to comment.