-
-
Save nicholasrq/7261367 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
### | |
"Stalkable" objects can be watched for any and all changes | |
@author Bryan Elliott <belliott@rsicms.com> | |
### | |
### | |
Detect whether an Object is using this Mixin | |
### | |
Ember.Mixin::detectInstance = (object) -> | |
#jslint forin:true | |
name = undefined | |
mixins = object[Ember.META_KEY].mixins | |
return Object.keys(mixins).reduce ((res, name)=> | |
return res && @detect(mixins[name]) | |
), true | |
### | |
Changes to Ember.CoreObject that enable property stalking via the pseudoproperties: "@properties", "@ownProperties", and "@prototypeProperties" | |
### | |
Ember.StalkableMixin = Ember.Mixin.create( | |
setUnknownProperty: (key, value) -> | |
ret = @_super?.apply(this, arguments) | |
@observeNewProperty key | |
return ret | |
observeNewProperty: (key, isProto) -> | |
inst = this | |
isInit = inst.constructor::hasOwnProperty(key) | |
clean = undefined | |
handler = -> | |
clean = not inst.modifiedProperties | |
if clean | |
inst.modifiedProperties = [key] | |
else | |
inst.modifiedProperties.push key | |
if not isProto and not isInit | |
inst.notifyPropertyChange "@ownProperties" | |
else if isInit and not isProto | |
inst.notifyPropertyChange "@initProperties" | |
else | |
inst.notifyPropertyChange "@prototypeProperties" | |
inst.notifyPropertyChange "@properties" | |
delete inst.modifiedProperties if clean | |
@addObserver key, this, handler | |
handler() unless isProto | |
setProperties: -> | |
ret = undefined | |
@modifiedProperties = [] | |
ret = @_super.apply(this, arguments) | |
delete @modifiedProperties | |
return ret | |
) | |
### | |
Small modification to CoreObject.create for Stalkables | |
### | |
Ember.CoreObject.reopenClass create: -> | |
#jslint forin:true | |
i = undefined | |
name = undefined | |
args = undefined | |
caught = {} | |
ret = @_super.apply(this, arguments) | |
if Ember.StalkableMixin.detectInstance(ret) | |
args = [].slice.apply(arguments) | |
i = 0 | |
while i < args.length | |
Object.keys(args[i]).forEach (name)-> | |
return true if args[i][name] instanceof Function | |
ret.observeNewProperty name | |
caught[name] = true | |
i += 1 | |
Object.keys(ret).forEach (name)-> | |
ret.observeNewProperty name, true unless caught[name] | |
ret | |
Ember.StalkableObject = Ember.Object.extend(Ember.StalkableMixin, {}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
### | |
The idea here is that all changes to your new object can be observed | |
### | |
Ember.View.extend | |
model: Ember.StalkableObject.create() | |
saveModel: Ember.observer(-> | |
### | |
do some fancy stuff to save changes to your model | |
### | |
, "model.@properties") | |
Ember.View.extend | |
model: Ember.StalkableObject.create( | |
host: null | |
port: null | |
) | |
saveModel: Ember.observer(-> | |
### | |
this will only be called when changes to the 'host' and 'port' are changed | |
### | |
, "model.@initProperties") | |
Ember.View.extend | |
model: App.MyStalkableModel.create() | |
saveModel: Ember.observer(-> | |
### | |
this will only be called when changes to the prototyped properties of App.MyStalkableModel are changed | |
### | |
, "model.@prototypeProperties") | |
Ember.View.extend | |
model: Ember.StalkableObject.create(nonce: null) | |
saveModel: Ember.observer(-> | |
### | |
this will be called on changes any properties that are undefined at instantiation (i.e., excluding all the | |
stuff on Object, as well as "nonce", which we expect to change frequently.) | |
### | |
, "model.@ownProperties") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment