Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions main.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,55 @@ module.exports = Observable = (value, context) ->
size: ->
magicDependency(self)
value.length
if Object::toString.call(value) is '[object Object]'
# proxy object properties and add notifications to mutation events
defProp = (property) ->
Object.defineProperty self, property,
get: ->
magicDependency(self)
# if object property is Observable, e.g obj = Observable { a: Observable 1 }
if typeof value[property]?.observe is "function"
value[property]()
else
value[property]
set: (val) ->
# if object property is Observable, e.g obj = Observable { a: Observable 1 }
if typeof value[property]?.observe is "function"
value[property] val
else
value[property] = val
notify value

defProp prop for own prop of value

# Proxy object methods, e.g. Object.keys(obj)
[
"keys"
"values"
"entries"
].forEach (method) ->
Object.defineProperty self, method,
get: ->
magicDependency(self)
Object[method] value

# Extra methods for object observables
extend self,
# Remove an element from the object and notify observers of changes.
remove: (object) ->
if returnValue = value[object]
delete value[object]
notify(value)
return returnValue

extend: (obj) ->
magicDependency(self)
value = Object.assign {}, value, obj
defProp prop for own prop of obj
notify value

# alias
self.assign = self.extend

extend self,
listeners: listeners
Expand Down
63 changes: 63 additions & 0 deletions test/observable.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -413,3 +413,66 @@ describe "Observable functions", ->
done()

model.lastName "Bro"

describe "Observable object", ->
it "should proxy properties", ->
obj = Observable
a: 1

assert.equal obj.a, 1
assert.equal obj().a, obj.a

obj.a = 2

assert.equal obj.a, 2
assert.equal obj().a, obj.a

it "should work with observable properties", ->
obj = Observable
a: Observable 1

assert.equal obj.a, 1
assert.equal obj().a(), obj.a

obj().a 2

assert.equal obj.a, 2
assert.equal obj().a(), obj.a

obj.a = 3

assert.equal obj.a, 3
assert.equal obj().a(), obj.a

it "should compute object#extend as a dependency", ->
obj = Observable
a: 1

obj.extend b: 2

assert.equal obj.b, 2
assert.equal obj().b, obj.b

# alias
obj.assign c: 3

assert.equal obj.c, 3
assert.equal obj().c, obj.c

it "should compute object#remove as a dependency", ->
obj = Observable
a: 1
b: 2

obj.remove "b"

assert.equal obj.b, undefined

it "should proxy object methods", ->
obj = Observable
a: 1
b: 2

assert.deepEqual obj.keys, ["a", "b"]
assert.deepEqual obj.values, [1, 2]
assert.deepEqual obj.entries, [["a", 1], ["b", 2]]