Last active
August 29, 2015 14:06
-
-
Save collingo/a4230b8f40f634d84ee2 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
// 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