Skip to content

Instantly share code, notes, and snippets.

@collingo
Last active August 29, 2015 14:06
Show Gist options
  • Save collingo/a4230b8f40f634d84ee2 to your computer and use it in GitHub Desktop.
Save collingo/a4230b8f40f634d84ee2 to your computer and use it in GitHub Desktop.
// simple path observing
function O(original, parentsWatcher, path) {
this.original = original;
this.path = path;
this.parentsWatcher = parentsWatcher;
Object.observe(this.original, function(changes) {
changes.forEach(function(change) {
if((change.type === 'add' || change.type === 'update') && typeof this.original[change.name] === "object") {
var child = new O(this.original[change.name], function(childPath, childNew, childOld) {
this.parentsWatcher(change.name+'.'+childPath, childNew, childOld);
}.bind(this), change.name);
}
this.parentsWatcher(change.name, this.original[change.name], change.oldValue);
}.bind(this));
}.bind(this));
}
var model = {};
var modelStream = new O(model, 'test', function(path, newValue, oldValue) {
console.log(path, JSON.stringify(newValue), JSON.stringify(oldValue));
});
function objectForEach(obj, cb) {
Object.keys(obj).forEach(function(key) {
cb(obj[key], key, obj);
});
}
function arrayForEach(arr, cb) {
arr.forEach(cb);
}
// simpler path observing
function pathObserver(obj, cb) {
function iterator(obj, cb, path) {
var type = Object;
var forEach = objectForEach;
if(Array.isArray(obj)) {
type = Array;
forEach = arrayForEach;
}
forEach(obj, function(val, key) {
if(typeof val === "object") {
iterator(val, cb, (path ? path+'.' : '')+key);
}
});
type.observe(obj, function(changes) {
while(changes.length) {
var change = changes.shift();
var cPath = (path ? path+'.' : '')+change.name;
var cType = change.type;
var cOld = change.oldValue;
var cNew;
switch(change.type) {
case 'add':
case 'update':
cNew = obj[change.name];
break;
case 'splice':
cPath = (path ? path+'.' : '')+change.index;
if(change.removed.length) {
console.log(change);
cType = 'remove';
cOld = change.removed[0];
if(change.removed.length > 1) {
changes.push({
addedCount: change.addedCount,
index: change.index + 1,
object: change.object,
removed: change.removed.slice(1),
type: change.type
});
}
} else if(change.addedCount) {
cType = 'add';
cNew = obj[change.index];
if(change.addedCount > 1) {
changes.push({
addedCount: change.addedCount - 1,
index: change.index + 1,
object: change.object,
removed: change.removed,
type: change.type
});
}
} else {
cType = 'update';
cOld = change.removed[0];
cNew = obj[change.index];
}
break;
}
if(typeof cNew === "object") {
iterator(cNew, cb, cPath);
}
cb(cPath, cType, cNew, cOld);
}
});
}
iterator(obj, cb);
}
var model2 = {
a:{
b:1,
d:[1,2,{
test:'hello',
carrot: 123
}]
},
c:2
};
pathObserver(model2, function(path, action, newValue, oldValue) {
console.log('path: ' + path, 'action: ' + action, 'new: ' + JSON.stringify(newValue), 'old: ' + JSON.stringify(oldValue));
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment