Skip to content

Instantly share code, notes, and snippets.

@Fordi
Forked from anonymous/stalkable.js
Created December 13, 2012 20:34
Show Gist options
  • Save Fordi/4279559 to your computer and use it in GitHub Desktop.
Save Fordi/4279559 to your computer and use it in GitHub Desktop.
/**
The idea here is that all changes to your new object can be observed
*/
Ember.View.extend({
model: Ember.StalkableObject.create(),
saveModel: Ember.observer(function () {
/** 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(function () {
/** 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(function () {
/** 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(function () {
/** 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')
});
/*jslint nomen:true */
/**
"Stalkable" objects can be watched for any and all changes
@author Bryan Elliott <[email protected]>
*/
(function (global) {
"use strict";
var Ember = global.Ember;
/**
Detect whether an Object is using this Mixin
*/
Ember.Mixin.prototype.detectInstance = function (object) {
/*jslint forin:true */
var name,
mixins = object[Ember.META_KEY].mixins;
for (name in mixins) {
if (this.detect(mixins[name])) {
return true;
}
}
return false;
};
/**
Changes to Ember.CoreObject that enable property stalking via the pseudoproperties: "@properties", "@ownProperties", and "@prototypeProperties"
*/
Ember.Stalkable = Ember.Mixin.create({
setUnknownProperty: function (key, value) {
var ret = this._super.apply(this, arguments);
this.observeNewProperty(key);
return ret;
},
observeNewProperty: function (key, isProto) {
var inst = this,
isInit = inst.constructor.prototype.hasOwnProperty(key),
clean,
handler = function () {
clean = !inst.modifiedProperties;
if (clean) {
inst.modifiedProperties = [ key ];
} else {
inst.modifiedProperties.push(key);
}
if (!isProto && !isInit) {
inst.notifyPropertyChange("@ownProperties");
} else if (isInit && !isProto) {
inst.notifyPropertyChange("@initProperties");
} else {
inst.notifyPropertyChange("@prototypeProperties");
}
inst.notifyPropertyChange("@properties");
if (clean) {
delete inst.modifiedProperties;
}
};
this.addObserver(key, this, handler);
if (!isProto) { handler(); }
},
setProperties: function () {
var ret;
this.modifiedProperties = [];
ret = this._super.apply(this, arguments);
delete this.modifiedProperties;
return ret;
}
});
/**
Small modification to CoreObject.create for Stalkables
*/
Ember.CoreObject.reopenClass({
create: function () {
/*jslint forin:true */
var i, name, args, caught = {},
ret = this._super.apply(this, arguments);
if (Ember.Stalkable.detectInstance(ret)) {
args = [].slice.apply(arguments);
for (i = 0; i < args.length; i += 1) {
for (name in args[i]) {
if (!(args[i][name] instanceof Function)) {
ret.observeNewProperty(name);
caught[name] = true;
}
}
}
for (name in ret) {
if (!caught[name]) {
ret.observeNewProperty(name, true)
}
}
}
return ret;
}
});
Ember.StalkableObject = Ember.Object.extend(Ember.Stalkable);
}(this));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment