-
-
Save arvindr21/322e4da27e52c0babc43e8f4ca2ddcac to your computer and use it in GitHub Desktop.
object.watch polyfill
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
/** | |
* DEVELOPED BY | |
* GIL LOPES BUENO | |
* gilbueno.mail@gmail.com | |
* | |
* LEARN HOW TO USE IT: | |
* http://watch.k6.com.br | |
* FORK: | |
* https://gist.github.com/1627705 | |
*/ | |
Object.prototype.watch = function() { | |
if (arguments.length == 1) | |
this.watchAll.apply(this, arguments); | |
else if (Array.isArray(arguments[0])) | |
this.watchMany.apply(this, arguments); | |
else | |
this.watchOne.apply(this, arguments); | |
} | |
Object.prototype.watchAll = function(watcher) { | |
var obj = this; | |
if (obj instanceof String || (!(obj instanceof Object) && !Array.isArray(obj))) //accepts only objects and array (not string) | |
return; | |
var props = []; | |
if(Array.isArray(obj)){ | |
for (var prop=0; prop<obj.length; prop++) { //for each item if obj is an array | |
props.push(prop); //put in the props | |
} | |
}else{ | |
for (var prop2 in obj) { //for each attribute if obj is an object | |
props.push(prop2); //put in the props | |
} | |
} | |
obj.watchMany(props, watcher); //watch all itens of the props | |
}; | |
Object.prototype.watchMany = function(props, watcher) { | |
var obj = this; | |
if(Array.isArray(obj)){ | |
for (var prop in props) { //watch each iten of "props" if is an array | |
obj.watchOne(props[prop], watcher); | |
} | |
}else{ | |
for (var prop2 in props) { //watch each attribute of "props" if is an object | |
obj.watchOne(props[prop2], watcher); | |
} | |
} | |
}; | |
Object.prototype.watchOne = function(prop, watcher) { | |
var obj = this; | |
var val = obj[prop]; | |
if(obj[prop]===undefined || isFunction(obj[prop]) || prop == "watchers" || prop == "__proto__") //dont watch if it is null, is a function, named "watchers" or "__proto__" | |
return; | |
if(obj[prop]!=null) | |
obj[prop].watchAll(watcher); //recursively watch all attributes of this | |
obj.watchFunctions(prop); | |
if (!obj.watchers) { | |
obj.watchers = {}; | |
} | |
if (!obj.watchers[prop]) | |
obj.watchers[prop] = []; | |
obj.watchers[prop].push(watcher); //add the new watcher in the watchers array | |
var getter = function() { | |
return val; | |
}; | |
var setter = function(newval) { | |
var oldval = val; | |
val = newval; | |
obj[prop].watchAll(watcher); | |
obj.watchFunctions(prop); | |
var oldvalAtr = oldval.attributes() || oldval; | |
var newvalAtr = newval.attributes() || newval; | |
if (JSON.stringify(oldvalAtr) != JSON.stringify(newvalAtr) && arguments.callee.caller != watcher) { | |
obj.callWatchers(prop); | |
} | |
}; | |
if (Object.defineProperty) { // ECMAScript 5 | |
Object.defineProperty(obj, prop, { | |
get: getter, | |
set: setter, | |
enumerable: true, | |
configurable: true | |
}); | |
} else if (Object.prototype.__defineGetter__ && Object.prototype.__defineSetter__) { // legacy | |
Object.prototype.__defineGetter__.call(obj, prop, getter); | |
Object.prototype.__defineSetter__.call(obj, prop, setter); | |
} | |
}; | |
Object.prototype.callWatchers = function(prop) { | |
var obj = this; | |
for (var wr in obj.watchers[prop]) { | |
if (isInt(wr)){ | |
obj.watchers[prop][wr](); | |
} | |
} | |
}; | |
Object.prototype.attributes = function(){ | |
var obj = this; | |
var response; | |
if(obj instanceof Boolean || obj instanceof Number || obj instanceof String){ | |
return obj; | |
}else if(Array.isArray(obj)){ | |
response = []; | |
for (var prop=0; prop<obj.length; prop++) { | |
if(!obj[prop] || isFunction(obj[prop]) || prop == "watchers" || prop == "__proto__") | |
continue; | |
if(obj[prop].attributes) | |
response.push(obj[prop].attributes()); | |
else | |
response.push(obj[prop]); | |
} | |
}else if(obj instanceof Object){ | |
response = {}; | |
for (var prop2 in obj) { | |
if(obj[prop2]===undefined || isFunction(obj[prop2]) || prop2 == "watchers" || prop2 == "__proto__") | |
continue; | |
if(obj[prop2] && obj[prop2].attributes) | |
response[prop2] = obj[prop2].attributes(); | |
else | |
response[prop2] = obj[prop2]; | |
} | |
}else{ | |
return obj; | |
} | |
return response; | |
}; | |
Object.prototype.watchFunctions = function(prop) { | |
var obj = this; | |
if(!obj[prop]) | |
return; | |
if (!(obj[prop] instanceof String) && (Array.isArray(obj[prop]))) {//is array? | |
obj[prop].pop = (function() { | |
var original = Array.prototype.pop; | |
return function() { | |
var response = original.apply(this, arguments); | |
obj.watchOne(obj[prop]); | |
obj.callWatchers(prop); | |
return response; | |
}; | |
})(); | |
obj[prop].push = (function() { | |
var original = Array.prototype.push; | |
return function() { | |
var response = original.apply(this, arguments); | |
obj.watchOne(obj[prop]); | |
obj.callWatchers(prop); | |
return response; | |
}; | |
})(); | |
obj[prop].reverse = (function() { | |
var original = Array.prototype.reverse; | |
return function() { | |
var response = original.apply(this, arguments); | |
obj.watchOne(obj[prop]); | |
obj.callWatchers(prop); | |
return response; | |
}; | |
})(); | |
obj[prop].shift = (function() { | |
var original = Array.prototype.shift; | |
return function() { | |
var response = original.apply(this, arguments); | |
obj.watchOne(obj[prop]); | |
obj.callWatchers(prop); | |
return response; | |
}; | |
})(); | |
obj[prop].sort = (function() { | |
var original = Array.prototype.sort; | |
return function() { | |
var response = original.apply(this, arguments); | |
obj.watchOne(obj[prop]); | |
obj.callWatchers(prop); | |
return response; | |
}; | |
})(); | |
obj[prop].splice = (function() { | |
var original = Array.prototype.splice; | |
return function() { | |
var response = original.apply(this, arguments); | |
obj.watchOne(obj[prop]); | |
obj.callWatchers(prop); | |
return response; | |
}; | |
})(); | |
obj[prop].unshift = (function() { | |
var original = Array.prototype.unshift; | |
return function() { | |
var response = original.apply(this, arguments); | |
obj.watchOne(obj[prop]); | |
obj.callWatchers(prop); | |
return response; | |
}; | |
})(); | |
} | |
}; | |
function isFunction(functionToCheck) { | |
var getType = {}; | |
return functionToCheck && getType.toString.call(functionToCheck) == '[object Function]'; | |
} | |
function isInt(x) { | |
var y = parseInt(x); | |
if (isNaN(y)) return false; | |
return x == y && x.toString() == y.toString(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment