Skip to content

Instantly share code, notes, and snippets.

@jpiccari
Last active August 29, 2015 14:01
Show Gist options
  • Save jpiccari/e811d02b4eda69edfb74 to your computer and use it in GitHub Desktop.
Save jpiccari/e811d02b4eda69edfb74 to your computer and use it in GitHub Desktop.
An improved observer that tracks changes to existing object properties while still allowing native object access. Should be supported in IE8+, Firefox, Chrome, Safari, etc. (235 bytes minified, gzipped)
define(
'observer',
[
'EventEmitter'
],
function(EventEmitter) {
'use strict';
var OBSERVER_KEY = '_isObserver',
isStandardDefineProperties = true;
try {
Object.defineProperties(new Object(), {});
} catch(e) {
// Must be IE8, we'll have to use a DOM Object :\
isStandardDefineProperties = false;
}
function defineProperties(object, options) {
if (!isStandardDefineProperties) {
object = document.createElement('div');
}
return Object.defineProperties(object, options);
}
return function observer(object) {
var properties = {},
options = {},
eventKeys = {},
key;
options[OBSERVER_KEY] = {
value: true,
writeable: false
};
for (key in object) {
if (typeof object[key] === 'object') {
object[key] = observer(object[key]);
eventKeys[key] = object[key];
}
properties[key] = object[key];
options[key] = (function(key) {
return {
get: function() {
return properties[key];
},
set: function(value) {
if (value !== properties[key]) {
if (typeof value === 'object' && !value[OBSERVER_KEY]) {
value = observer(value);
}
var change = {
type: 'updated',
object: this,
name: key,
oldValue: properties[key],
value: value
};
properties[key] = value;
this.trigger('change', change);
}
}
};
}(key));
}
object = EventEmitter(defineProperties(object, options));
for (key in eventKeys) {
eventKeys[key].on('change', function(change) {
change.name = key + '.' + change.name;
object.trigger('change', change);
});
}
return object;
};
}
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment