Skip to content

Instantly share code, notes, and snippets.

@Unitech
Forked from melanke/README.md
Created July 20, 2012 11:41
Show Gist options
  • Save Unitech/3150291 to your computer and use it in GitHub Desktop.
Save Unitech/3150291 to your computer and use it in GitHub Desktop.

Revisions

  1. @melanke melanke revised this gist Jun 20, 2012. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -1,7 +1,7 @@
    # Watch.js
    # Watch.js 1.0.13

    ##compatibility
    Works with: 1.0.13 (IE 9+, FF 4+, SF 5+, WebKit, CH 7+, OP 12+, BESEN, Rhino 1.7+)
    Works with: IE 9+, FF 4+, SF 5+, WebKit, CH 7+, OP 12+, BESEN, Rhino 1.7+
    If you want a similar API that works for all browser try [MultiGetSet](https://gist.github.com/2956493)

    ## About
  2. @melanke melanke revised this gist Jun 20, 2012. 1 changed file with 5 additions and 1 deletion.
    6 changes: 5 additions & 1 deletion README.md
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,8 @@
    # Watch.js 1.0.13 (IE 9+, FF 4+, SF 5+, WebKit, CH 7+, OP 12+, BESEN, Rhino 1.7+)
    # Watch.js

    ##compatibility
    Works with: 1.0.13 (IE 9+, FF 4+, SF 5+, WebKit, CH 7+, OP 12+, BESEN, Rhino 1.7+)
    If you want a similar API that works for all browser try [MultiGetSet](https://gist.github.com/2956493)

    ## About

  3. @melanke melanke revised this gist Jun 14, 2012. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion README.md
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,4 @@
    # Watch.js 1.0.12 ()
    # Watch.js 1.0.13 (IE 9+, FF 4+, SF 5+, WebKit, CH 7+, OP 12+, BESEN, Rhino 1.7+)

    ## About

  4. @melanke melanke revised this gist Jun 14, 2012. 2 changed files with 160 additions and 203 deletions.
    2 changes: 1 addition & 1 deletion README.md
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,4 @@
    # Watch.js 1.0.12
    # Watch.js 1.0.12 ()

    ## About

    361 changes: 159 additions & 202 deletions watch.js
    Original file line number Diff line number Diff line change
    @@ -3,6 +3,9 @@
    * GIL LOPES BUENO
    * [email protected]
    *
    * WORKS WITH:
    * IE 9+, FF 4+, SF 5+, WebKit, CH 7+, OP 12+, BESEN, Rhino 1.7+
    *
    * FORK:
    * https://gist.github.com/1627705
    */
    @@ -17,277 +20,231 @@ var $watchjs$ = {
    var y = parseInt(x);
    if (isNaN(y)) return false;
    return x == y && x.toString() == y.toString();
    },
    isArray: function(obj) {
    return Object.prototype.toString.call(obj) === '[object Array]';
    },
    defineGetAndSet: function(obj, propName, getter, setter){
    try{
    Object.defineProperty(obj, propName, {
    get: getter,
    set: setter,
    enumerable: true,
    configurable: true
    });
    }catch(error){
    try{
    Object.prototype.__defineGetter__.call(obj, propName, getter);
    Object.prototype.__defineSetter__.call(obj, propName, setter);
    }catch(error2){
    throw "watchJS error: browser not supported :/"
    }
    }
    },
    defineProp: function(obj, propName, value){
    try{
    Object.defineProperty(obj, propName, {
    enumerable: false
    , configurable: true
    , writable: false
    , value: value
    });
    }catch(error){
    obj[propName] = value;
    }
    }
    };

    Object.defineProperty(Object.prototype, "watch", {
    enumerable: false
    , configurable: true
    , writable: false
    , value: function() {
    $watchjs$.defineProp(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);
    if (arguments.length == 1)
    this.watchAll.apply(this, arguments);
    else if ($watchjs$.isArray(arguments[0]))
    this.watchMany.apply(this, arguments);
    else
    this.watchOne.apply(this, arguments);

    }
    });


    Object.defineProperty(Object.prototype, "watchAll", {
    enumerable: false
    , configurable: true
    , writable: false
    , value: function(watcher) {
    $watchjs$.defineProp(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 obj = this;

    var props = [];
    if (obj instanceof String || (!(obj instanceof Object) && !$watchjs$.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
    }
    if($watchjs$.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.defineProperty(Object.prototype, "watchMany", {
    enumerable: false
    , configurable: true
    , writable: false
    , value: 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);
    }
    }
    }
    $watchjs$.defineProp(Object.prototype, "watchMany", function(props, watcher) {
    var obj = this;

    if($watchjs$.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.defineProperty(Object.prototype, "watchOne", {
    enumerable: false
    , configurable: true
    , writable: false
    , value: function(prop, watcher) {
    var obj = this;
    $watchjs$.defineProp(Object.prototype, "watchOne", function(prop, watcher) {
    var obj = this;

    var val = obj[prop];
    var val = obj[prop];

    if(obj[prop]===undefined || $watchjs$.isFunction(obj[prop])) //dont watch if it is null or a function
    return;
    if(obj[prop]===undefined || $watchjs$.isFunction(obj[prop])) //dont watch if it is null or a function
    return;

    if(obj[prop]!=null)
    obj[prop].watchAll(watcher); //recursively watch all attributes of this
    if(obj[prop]!=null)
    obj[prop].watchAll(watcher); //recursively watch all attributes of this

    obj.watchFunctions(prop);
    obj.watchFunctions(prop);


    if (!obj.watchers) {
    Object.defineProperty(obj, "watchers", {
    enumerable: false
    , configurable: true
    , writable: false
    , value: {}
    });
    }
    if (!obj.watchers) {
    $watchjs$.defineProp(obj, "watchers", {});
    }

    if (!obj.watchers[prop])
    obj.watchers[prop] = [];
    if (!obj.watchers[prop])
    obj.watchers[prop] = [];


    obj.watchers[prop].push(watcher); //add the new watcher in the watchers array
    obj.watchers[prop].push(watcher); //add the new watcher in the watchers array


    var getter = function() {
    return val;
    };
    var getter = function() {
    return val;
    };


    var setter = function(newval) {
    var oldval = val;
    val = newval;

    if(obj[prop])
    obj[prop].watchAll(watcher);

    obj.watchFunctions(prop);
    var setter = function(newval) {
    var oldval = val;
    val = newval;

    if (JSON.stringify(oldval) != JSON.stringify(newval) && arguments.callee.caller != watcher) {
    obj.callWatchers(prop);
    }
    };
    if(obj[prop])
    obj[prop].watchAll(watcher);

    Object.defineProperty(obj, prop, {
    get: getter,
    set: setter,
    enumerable: true,
    configurable: true
    });
    obj.watchFunctions(prop);

    if (JSON.stringify(oldval) != JSON.stringify(newval) && arguments.callee.caller != watcher) {
    obj.callWatchers(prop);
    }
    };

    }
    });
    $watchjs$.defineGetAndSet(obj, prop, getter, setter);

    Object.defineProperty(Object.prototype, "callWatchers", {
    enumerable: false
    , configurable: true
    , writable: false
    , value: function(prop) {
    var obj = this;

    for (var wr in obj.watchers[prop]) {
    if ($watchjs$.isInt(wr)){
    obj.watchers[prop][wr]();
    }
    }
    }
    });

    $watchjs$.defineProp(Object.prototype, "callWatchers", function(prop) {
    var obj = this;

    for (var wr in obj.watchers[prop]) {
    if ($watchjs$.isInt(wr)){
    obj.watchers[prop][wr]();
    }
    }
    });



    Object.defineProperty(Object.prototype, "watchFunctions", {
    enumerable: false
    , configurable: true
    , writable: false
    , value: function(prop) {
    var obj = this;
    $watchjs$.defineProp(Object.prototype, "watchFunctions", function(prop) {
    var obj = this;

    if((!obj[prop]) || (obj[prop] instanceof String) || (!Array.isArray(obj[prop])))
    return;

    var originalpop = obj[prop].pop;
    Object.defineProperty(obj[prop], "pop", {
    enumerable: false,
    configurable: true,
    writable: false,
    value: function() {
    var response = originalpop.apply(this, arguments);

    obj.watchOne(obj[prop]);
    obj.callWatchers(prop);
    if((!obj[prop]) || (obj[prop] instanceof String) || (!$watchjs$.isArray(obj[prop])))
    return;

    var originalpop = obj[prop].pop;
    $watchjs$.defineProp(obj[prop], "pop", function() {
    var response = originalpop.apply(this, arguments);

    obj.watchOne(obj[prop]);
    obj.callWatchers(prop);

    return response;
    }
    });
    return response;
    });


    var originalpush = obj[prop].push;
    Object.defineProperty(obj[prop], "push", {
    enumerable: false,
    configurable: true,
    writable: false,
    value: function() {
    var response = originalpush.apply(this, arguments);
    var originalpush = obj[prop].push;
    $watchjs$.defineProp(obj[prop], "push", function() {
    var response = originalpush.apply(this, arguments);

    obj.watchOne(obj[prop]);
    obj.callWatchers(prop);
    obj.watchOne(obj[prop]);
    obj.callWatchers(prop);

    return response;
    }
    });
    return response;
    });


    var originalreverse = obj[prop].reverse;
    Object.defineProperty(obj[prop], "reverse", {
    enumerable: false,
    configurable: true,
    writable: false,
    value: function() {
    var response = originalreverse.apply(this, arguments);
    var originalreverse = obj[prop].reverse;
    $watchjs$.defineProp(obj[prop], "reverse", function() {
    var response = originalreverse.apply(this, arguments);

    obj.watchOne(obj[prop]);
    obj.callWatchers(prop);
    obj.watchOne(obj[prop]);
    obj.callWatchers(prop);

    return response;
    }
    });
    return response;
    });


    var originalshift = obj[prop].shift;
    Object.defineProperty(obj[prop], "shift", {
    enumerable: false,
    configurable: true,
    writable: false,
    value: function() {
    var response = originalshift.apply(this, arguments);
    var originalshift = obj[prop].shift;
    $watchjs$.defineProp(obj[prop], "shift", function() {
    var response = originalshift.apply(this, arguments);

    obj.watchOne(obj[prop]);
    obj.callWatchers(prop);
    obj.watchOne(obj[prop]);
    obj.callWatchers(prop);

    return response;
    }
    });
    return response;
    });


    var originalsort = obj[prop].sort;
    Object.defineProperty(obj[prop], "sort", {
    enumerable: false,
    configurable: true,
    writable: false,
    value: function() {
    var response = originalsort.apply(this, arguments);
    var originalsort = obj[prop].sort;
    $watchjs$.defineProp(obj[prop], "sort", function() {
    var response = originalsort.apply(this, arguments);

    obj.watchOne(obj[prop]);
    obj.callWatchers(prop);
    obj.watchOne(obj[prop]);
    obj.callWatchers(prop);

    return response;
    }
    });
    return response;
    });


    var originalslice = obj[prop].slice;
    Object.defineProperty(obj[prop], "slice", {
    enumerable: false,
    configurable: true,
    writable: false,
    value: function() {
    var response = originalslice.apply(this, arguments);
    var originalslice = obj[prop].slice;
    $watchjs$.defineProp(obj[prop], "slice", function() {
    var response = originalslice.apply(this, arguments);

    obj.watchOne(obj[prop]);
    obj.watchOne(obj[prop]);

    return response;
    }
    });
    return response;
    });


    var originalunshift = obj[prop].unshift;
    Object.defineProperty(obj[prop], "unshift", {
    enumerable: false,
    configurable: true,
    writable: false,
    value: function() {
    var response = originalunshift.apply(this, arguments);
    var originalunshift = obj[prop].unshift;
    $watchjs$.defineProp(obj[prop], "unshift", function() {
    var response = originalunshift.apply(this, arguments);

    obj.watchOne(obj[prop]);
    obj.callWatchers(prop);
    obj.watchOne(obj[prop]);
    obj.callWatchers(prop);

    return response;
    }
    });
    return response;
    });

    }
    });
  5. @melanke melanke revised this gist Jun 11, 2012. 2 changed files with 92 additions and 78 deletions.
    2 changes: 1 addition & 1 deletion README.md
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,4 @@
    # Watch.js 1.0.11
    # Watch.js 1.0.12

    ## About

    168 changes: 91 additions & 77 deletions watch.js
    Original file line number Diff line number Diff line change
    @@ -129,9 +129,9 @@ Object.defineProperty(Object.prototype, "watchOne", {
    var setter = function(newval) {
    var oldval = val;
    val = newval;

    if(obj[prop])
    obj[prop].watchAll(watcher);
    obj[prop].watchAll(watcher);

    obj.watchFunctions(prop);

    @@ -140,17 +140,12 @@ Object.defineProperty(Object.prototype, "watchOne", {
    }
    };

    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);
    }


    }
    @@ -179,101 +174,120 @@ Object.defineProperty(Object.prototype, "watchFunctions", {
    , configurable: true
    , writable: false
    , value: function(prop) {
    var obj = this;

    if((!obj[prop]) || (obj[prop] instanceof String) || (!Array.isArray(obj[prop])))
    return;

    obj[prop].pop = (function() {
    var original = Array.prototype.pop;
    return function() {
    var response = original.apply(this, arguments);

    obj.watchOne(obj[prop]);
    obj.callWatchers(prop);
    var obj = this;

    return response;
    };
    })();
    if((!obj[prop]) || (obj[prop] instanceof String) || (!Array.isArray(obj[prop])))
    return;

    var originalpop = obj[prop].pop;
    Object.defineProperty(obj[prop], "pop", {
    enumerable: false,
    configurable: true,
    writable: false,
    value: function() {
    var response = originalpop.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);
    var originalpush = obj[prop].push;
    Object.defineProperty(obj[prop], "push", {
    enumerable: false,
    configurable: true,
    writable: false,
    value: function() {
    var response = originalpush.apply(this, arguments);

    return response;
    };
    })();
    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);
    var originalreverse = obj[prop].reverse;
    Object.defineProperty(obj[prop], "reverse", {
    enumerable: false,
    configurable: true,
    writable: false,
    value: function() {
    var response = originalreverse.apply(this, arguments);

    return response;
    };
    })();
    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);
    var originalshift = obj[prop].shift;
    Object.defineProperty(obj[prop], "shift", {
    enumerable: false,
    configurable: true,
    writable: false,
    value: function() {
    var response = originalshift.apply(this, arguments);

    return response;
    };
    })();
    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);
    var originalsort = obj[prop].sort;
    Object.defineProperty(obj[prop], "sort", {
    enumerable: false,
    configurable: true,
    writable: false,
    value: function() {
    var response = originalsort.apply(this, arguments);

    return response;
    };
    })();
    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);
    var originalslice = obj[prop].slice;
    Object.defineProperty(obj[prop], "slice", {
    enumerable: false,
    configurable: true,
    writable: false,
    value: function() {
    var response = originalslice.apply(this, arguments);

    return response;
    };
    })();
    obj.watchOne(obj[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);
    var originalunshift = obj[prop].unshift;
    Object.defineProperty(obj[prop], "unshift", {
    enumerable: false,
    configurable: true,
    writable: false,
    value: function() {
    var response = originalunshift.apply(this, arguments);

    return response;
    };
    })();
    obj.watchOne(obj[prop]);
    obj.callWatchers(prop);

    }
    return response;
    }
    });

    }
    });
  6. @melanke melanke revised this gist Jun 6, 2012. 2 changed files with 70 additions and 94 deletions.
    2 changes: 1 addition & 1 deletion README.md
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,4 @@
    # Watch.js
    # Watch.js 1.0.11

    ## About

    162 changes: 69 additions & 93 deletions object-watch.js → watch.js
    Original file line number Diff line number Diff line change
    @@ -130,7 +130,9 @@ Object.defineProperty(Object.prototype, "watchOne", {
    var oldval = val;
    val = newval;

    if(obj[prop])
    obj[prop].watchAll(watcher);

    obj.watchFunctions(prop);

    if (JSON.stringify(oldval) != JSON.stringify(newval) && arguments.callee.caller != watcher) {
    @@ -177,127 +179,101 @@ Object.defineProperty(Object.prototype, "watchFunctions", {
    , configurable: true
    , writable: false
    , value: function(prop) {
    var obj = this;
    var obj = this;

    if(!obj[prop])
    return;
    if((!obj[prop]) || (obj[prop] instanceof String) || (!Array.isArray(obj[prop])))
    return;

    if (!(obj[prop] instanceof String) && (Array.isArray(obj[prop]))) {//is array?

    var originalpop = Array.prototype.pop;
    Object.defineProperty(Object.prototype, "pop", {
    enumerable: false
    , configurable: true
    , writable: false
    , value: function() {
    var response = originalpop.apply(this, arguments);

    obj.watchOne(obj[prop]);
    obj.callWatchers(prop);

    return response;
    }
    });
    obj[prop].pop = (function() {
    var original = Array.prototype.pop;
    return function() {
    var response = original.apply(this, arguments);

    obj.watchOne(obj[prop]);
    obj.callWatchers(prop);

    var originalpush = Array.prototype.push;
    Object.defineProperty(Object.prototype, "push", {
    enumerable: false
    , configurable: true
    , writable: false
    , value: function() {
    var response = originalpush.apply(this, arguments);
    return response;
    };
    })();

    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);

    var originalreverse = Array.prototype.reverse;
    Object.defineProperty(Object.prototype, "reverse", {
    enumerable: false
    , configurable: true
    , writable: false
    , value: function() {
    var response = originalreverse.apply(this, arguments);
    return response;
    };
    })();

    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);

    var originalshift = Array.prototype.shift;
    Object.defineProperty(Object.prototype, "shift", {
    enumerable: false
    , configurable: true
    , writable: false
    , value: function() {
    var response = originalshift.apply(this, arguments);
    return response;
    };
    })();

    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);

    var originalsort = Array.prototype.sort;
    Object.defineProperty(Object.prototype, "sort", {
    enumerable: false
    , configurable: true
    , writable: false
    , value: function() {
    var response = originalsort.apply(this, arguments);
    return response;
    };
    })();

    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);

    var originalslice = Array.prototype.slice;
    Object.defineProperty(Object.prototype, "slice", {
    enumerable: false
    , configurable: true
    , writable: false
    , value: function() {
    var response = originalslice.apply(this, arguments);
    return response;
    };
    })();

    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);

    var originalunshift = Array.prototype.unshift;
    Object.defineProperty(Object.prototype, "unshift", {
    enumerable: false
    , configurable: true
    , writable: false
    , value: function() {
    var response = originalunshift.apply(this, arguments);
    return response;
    };
    })();

    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;
    };
    })();

    }

    }
    });
  7. @melanke melanke revised this gist Jun 1, 2012. 1 changed file with 64 additions and 43 deletions.
    107 changes: 64 additions & 43 deletions object-watch.js
    Original file line number Diff line number Diff line change
    @@ -183,96 +183,117 @@ Object.defineProperty(Object.prototype, "watchFunctions", {
    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);

    var originalpop = Array.prototype.pop;
    Object.defineProperty(Object.prototype, "pop", {
    enumerable: false
    , configurable: true
    , writable: false
    , value: function() {
    var response = originalpop.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);
    var originalpush = Array.prototype.push;
    Object.defineProperty(Object.prototype, "push", {
    enumerable: false
    , configurable: true
    , writable: false
    , value: function() {
    var response = originalpush.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);
    var originalreverse = Array.prototype.reverse;
    Object.defineProperty(Object.prototype, "reverse", {
    enumerable: false
    , configurable: true
    , writable: false
    , value: function() {
    var response = originalreverse.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);
    var originalshift = Array.prototype.shift;
    Object.defineProperty(Object.prototype, "shift", {
    enumerable: false
    , configurable: true
    , writable: false
    , value: function() {
    var response = originalshift.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);
    var originalsort = Array.prototype.sort;
    Object.defineProperty(Object.prototype, "sort", {
    enumerable: false
    , configurable: true
    , writable: false
    , value: function() {
    var response = originalsort.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);
    var originalslice = Array.prototype.slice;
    Object.defineProperty(Object.prototype, "slice", {
    enumerable: false
    , configurable: true
    , writable: false
    , value: function() {
    var response = originalslice.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);
    var originalunshift = Array.prototype.unshift;
    Object.defineProperty(Object.prototype, "unshift", {
    enumerable: false
    , configurable: true
    , writable: false
    , value: function() {
    var response = originalunshift.apply(this, arguments);

    obj.watchOne(obj[prop]);
    obj.callWatchers(prop);

    return response;
    };
    })();
    }
    });

    }

  8. @melanke melanke revised this gist Apr 23, 2012. 2 changed files with 47 additions and 116 deletions.
    28 changes: 0 additions & 28 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -89,34 +89,6 @@ ex4.attr2 = 2; //attr2 will be changed to 2 and inside the watcher it will be ch

    [Try out](http://jsfiddle.net/JHYeD/2/)

    ## Getting the whole object by itself

    By declaring a watcher for an attribute of some object you will create getters and setter for this attribute. So if you want get all the attributes of your object (ex.: Serialize the object) you should use the method attributes()

    ```javascript
    //defining our object no matter which way we want
    var ex5 = {
    attr1: 0,
    attr2: 1,
    attr3: ["a", 3, null]
    };

    //defining a 'watcher' for the object
    ex5.watch(function(){
    alert("some attribute of ex5 changes!")
    });
    //after that attr1, attr2 and attr3 will be only accessibles by getters and setters

    ex5.attr1 = 2; //invoking a setter
    var temp = ex5.attr1; //invoking a getter and assigning the return to a variable called temp

    var attributes = ext.attributes();

    var jsonAttributes = JSON.stringify(attributes);
    ```

    [Try out](http://jsfiddle.net/BjLCd/)

    ## Chill out, no surprises, new attributes will not be considered

    After declaring a watcher for some object, when you add new attributes for this object and/or change it, the watcher will not be invoked. If you want the new attributes to be observed you only need to add the watcher to these new attributes again.
    135 changes: 47 additions & 88 deletions object-watch.js
    Original file line number Diff line number Diff line change
    @@ -7,11 +7,24 @@
    * https://gist.github.com/1627705
    */

    var $watchjs$ = {
    isFunction: function(functionToCheck) {
    var getType = {};
    return functionToCheck && getType.toString.call(functionToCheck) == '[object Function]';
    },

    isInt: function(x) {
    var y = parseInt(x);
    if (isNaN(y)) return false;
    return x == y && x.toString() == y.toString();
    }
    };

    Object.defineProperty(Object.prototype, "watch", {
    enumerable: false
    , configurable: true
    , writable: false
    , value: function() {
    enumerable: false
    , configurable: true
    , writable: false
    , value: function() {

    if (arguments.length == 1)
    this.watchAll.apply(this, arguments);
    @@ -25,10 +38,10 @@ Object.defineProperty(Object.prototype, "watch", {


    Object.defineProperty(Object.prototype, "watchAll", {
    enumerable: false
    , configurable: true
    , writable: false
    , value: function(watcher) {
    enumerable: false
    , configurable: true
    , writable: false
    , value: function(watcher) {

    var obj = this;

    @@ -55,10 +68,10 @@ Object.defineProperty(Object.prototype, "watchAll", {


    Object.defineProperty(Object.prototype, "watchMany", {
    enumerable: false
    , configurable: true
    , writable: false
    , value: function(props, watcher) {
    enumerable: false
    , configurable: true
    , writable: false
    , value: function(props, watcher) {
    var obj = this;

    if(Array.isArray(obj)){
    @@ -75,15 +88,15 @@ Object.defineProperty(Object.prototype, "watchMany", {
    });

    Object.defineProperty(Object.prototype, "watchOne", {
    enumerable: false
    , configurable: true
    , writable: false
    , value: function(prop, watcher) {
    enumerable: false
    , configurable: true
    , writable: false
    , value: 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__"
    if(obj[prop]===undefined || $watchjs$.isFunction(obj[prop])) //dont watch if it is null or a function
    return;

    if(obj[prop]!=null)
    @@ -93,7 +106,12 @@ Object.defineProperty(Object.prototype, "watchOne", {


    if (!obj.watchers) {
    obj.watchers = {};
    Object.defineProperty(obj, "watchers", {
    enumerable: false
    , configurable: true
    , writable: false
    , value: {}
    });
    }

    if (!obj.watchers[prop])
    @@ -115,10 +133,7 @@ Object.defineProperty(Object.prototype, "watchOne", {
    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) {
    if (JSON.stringify(oldval) != JSON.stringify(newval) && arguments.callee.caller != watcher) {
    obj.callWatchers(prop);
    }
    };
    @@ -140,71 +155,28 @@ Object.defineProperty(Object.prototype, "watchOne", {
    });

    Object.defineProperty(Object.prototype, "callWatchers", {
    enumerable: false
    , configurable: true
    , writable: false
    , value: function(prop) {
    enumerable: false
    , configurable: true
    , writable: false
    , value: function(prop) {
    var obj = this;

    for (var wr in obj.watchers[prop]) {
    if (isInt(wr)){
    if ($watchjs$.isInt(wr)){
    obj.watchers[prop][wr]();
    }
    }
    }

    });

    Object.defineProperty(Object.prototype, "attributes", {
    enumerable: false
    , configurable: true
    , writable: false
    , value: 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.defineProperty(Object.prototype, "watchFunctions", {
    enumerable: false
    , configurable: true
    , writable: false
    , value: function(prop) {
    enumerable: false
    , configurable: true
    , writable: false
    , value: function(prop) {
    var obj = this;

    if(!obj[prop])
    @@ -307,17 +279,4 @@ Object.defineProperty(Object.prototype, "watchFunctions", {


    }
    });



    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();
    }
    });
  9. @melanke melanke revised this gist Apr 20, 2012. 1 changed file with 297 additions and 258 deletions.
    555 changes: 297 additions & 258 deletions object-watch.js
    Original file line number Diff line number Diff line change
    @@ -7,268 +7,307 @@
    * https://gist.github.com/1627705
    */

    Object.prototype.watch = function() {
    Object.defineProperty(Object.prototype, "watch", {
    enumerable: false
    , configurable: true
    , writable: false
    , value: 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);
    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.defineProperty(Object.prototype, "watchAll", {
    enumerable: false
    , configurable: true
    , writable: false
    , value: 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.defineProperty(Object.prototype, "watchMany", {
    enumerable: false
    , configurable: true
    , writable: false
    , value: 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.defineProperty(Object.prototype, "watchOne", {
    enumerable: false
    , configurable: true
    , writable: false
    , value: 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.defineProperty(Object.prototype, "callWatchers", {
    enumerable: false
    , configurable: true
    , writable: false
    , value: function(prop) {
    var obj = this;

    for (var wr in obj.watchers[prop]) {
    if (isInt(wr)){
    obj.watchers[prop][wr]();
    }
    }
    }

    });

    Object.defineProperty(Object.prototype, "attributes", {
    enumerable: false
    , configurable: true
    , writable: false
    , value: 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.defineProperty(Object.prototype, "watchFunctions", {
    enumerable: false
    , configurable: true
    , writable: false
    , value: 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;
    };
    })();

    }

    }


    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;
    };
    })();

    }



    };
    }
    });



  10. @melanke melanke revised this gist Apr 20, 2012. 1 changed file with 19 additions and 1 deletion.
    20 changes: 19 additions & 1 deletion README.md
    Original file line number Diff line number Diff line change
    @@ -156,4 +156,22 @@ ex7.watch(function(){
    ex7.callWatchers(); //invoke the watcher
    ```

    [Try out](http://jsfiddle.net/98MmB/)
    [Try out](http://jsfiddle.net/98MmB/)

    ## Compatible with JQuery

    ```javascript
    $(function(){

    var obj = {cont: 0};

    obj.watch("cont", function(){
    alert("obj.cont = "+obj.cont);
    });

    $("#button").click(function(){
    obj.cont++;
    });
    });
    ```
    [Try out](http://jsfiddle.net/fj2Yb/)
  11. @melanke melanke revised this gist Apr 19, 2012. 1 changed file with 135 additions and 1 deletion.
    136 changes: 135 additions & 1 deletion README.md
    Original file line number Diff line number Diff line change
    @@ -22,4 +22,138 @@ ex1.watch("attr1", function(){
    ex1.attr1 = "other value";
    ```

    [Try out](http://jsfiddle.net/NbJuh/)
    [Try out](http://jsfiddle.net/NbJuh/)

    ## Observe the changes of more than one object attribute

    ```javascript
    //defining our object no matter which way we want
    var ex2 = {
    attr1: 0,
    attr2: 0,
    attr3: 0
    };

    //defining a 'watcher' for the attributes
    ex2.watch(["attr2", "attr3"], function(){
    alert("attr2 or attr3 changes!");
    });

    //when changing one of the attributes its watcher will be invoked
    ex2.attr2 = 50;
    ```

    [Try out](http://jsfiddle.net/2zT4C/)

    ## Observe the changes of all attributes of the object

    ```javascript
    //defining our object no matter which way we want
    var ex3 = {
    attr1: 0,
    attr2: "initial value of attr2",
    attr3: ["a", 3, null]
    };

    //defining a 'watcher' for the object
    ex3.watch(function(){
    alert("some attribute of ex3 changes!");
    });

    //when changing one of the attributes of the object the watcher will be invoked
    ex3.attr3.push("new value");
    ```

    [Try out](http://jsfiddle.net/C83pW/)

    ## Don't worry about the Inifinite Loop

    Different of some libraries, with Watch.JS you will never to worry about inifinite loop when change the object inside its own watcher, the watcher will not be invoked from itself.

    ```javascript
    //defining our object no matter which way we want
    var ex4 = {
    attr1: 0,
    attr2: 1,
    attr3: ["a", 3, null]
    };

    //defining a 'watcher' for an attribute
    ex4.watch("attr2", function(){
    alert("attr2 changes");
    ex4.attr2 = ex4.attr2 * 2; //will not invoke the watcher
    });

    ex4.attr2 = 2; //attr2 will be changed to 2 and inside the watcher it will be changed to 4
    ```

    [Try out](http://jsfiddle.net/JHYeD/2/)

    ## Getting the whole object by itself

    By declaring a watcher for an attribute of some object you will create getters and setter for this attribute. So if you want get all the attributes of your object (ex.: Serialize the object) you should use the method attributes()

    ```javascript
    //defining our object no matter which way we want
    var ex5 = {
    attr1: 0,
    attr2: 1,
    attr3: ["a", 3, null]
    };

    //defining a 'watcher' for the object
    ex5.watch(function(){
    alert("some attribute of ex5 changes!")
    });
    //after that attr1, attr2 and attr3 will be only accessibles by getters and setters

    ex5.attr1 = 2; //invoking a setter
    var temp = ex5.attr1; //invoking a getter and assigning the return to a variable called temp

    var attributes = ext.attributes();

    var jsonAttributes = JSON.stringify(attributes);
    ```

    [Try out](http://jsfiddle.net/BjLCd/)

    ## Chill out, no surprises, new attributes will not be considered

    After declaring a watcher for some object, when you add new attributes for this object and/or change it, the watcher will not be invoked. If you want the new attributes to be observed you only need to add the watcher to these new attributes again.

    ```javascript
    //defining our object no matter which way we want
    var ex6 = {
    attr1: 0,
    attr2: 1
    };

    //defining a 'watcher' for the object
    ex6.watch(function(){
    alert("some attribute of ex6 changes!")
    });

    ex6.attr3 = null; //no watcher will be invoked
    ex6.attr3 = "value"; //no watcher will be invoked
    ```

    [Try out](http://jsfiddle.net/NFmUc/)

    ## Invoke the watcher anytime you want

    ```javascript
    //defining our object no matter which way we want
    var ex7 = {
    attr1: 0,
    attr2: 1
    };

    //defining a 'watcher' for the object
    ex7.watch(function(){
    alert("some attribute of ex6 changes!")
    });

    ex7.callWatchers(); //invoke the watcher
    ```

    [Try out](http://jsfiddle.net/98MmB/)
  12. @melanke melanke revised this gist Apr 19, 2012. 2 changed files with 25 additions and 2 deletions.
    25 changes: 25 additions & 0 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,25 @@
    # Watch.js

    ## About

    Watch.JS is a small library that brings a lot of possibilities. Maybe you know the design pattern called "Observer", imagine the possibility of executing some function always that some object changes. Well, already exists other libraries that do this, but with Watch.JS you will not have to change your way to develop. Give a chance to Watch.JS, take a look at the examples and how is simple to embody Watch.JS to your routine.

    ## Observe the changes of one object attribute

    ```javascript
    //defining our object no matter which way we want
    var ex1 = {
    attr1: "initial value of attr1",
    attr2: "initial value of attr2"
    };

    //defining a 'watcher' for an attribute
    ex1.watch("attr1", function(){
    alert("attr1 changes!");
    });

    //when changing the attribute its watcher will be invoked
    ex1.attr1 = "other value";
    ```

    [Try out](http://jsfiddle.net/NbJuh/)
    2 changes: 0 additions & 2 deletions object-watch.js
    Original file line number Diff line number Diff line change
    @@ -3,8 +3,6 @@
    * GIL LOPES BUENO
    * [email protected]
    *
    * LEARN HOW TO USE IT:
    * http://watch.k6.com.br
    * FORK:
    * https://gist.github.com/1627705
    */
  13. @melanke melanke revised this gist Feb 15, 2012. 1 changed file with 4 additions and 2 deletions.
    6 changes: 4 additions & 2 deletions object-watch.js
    Original file line number Diff line number Diff line change
    @@ -63,10 +63,12 @@ Object.prototype.watchOne = function(prop, watcher) {

    var val = obj[prop];

    if(!obj[prop] || isFunction(obj[prop]) || prop == "watchers" || prop == "__proto__") //dont watch if it is null, is a function, named "watchers" or "__proto__"
    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;

    obj[prop].watchAll(watcher); //recursively watch all attributes of this
    if(obj[prop]!=null)
    obj[prop].watchAll(watcher); //recursively watch all attributes of this

    obj.watchFunctions(prop);


  14. @melanke melanke revised this gist Feb 14, 2012. 1 changed file with 4 additions and 4 deletions.
    8 changes: 4 additions & 4 deletions object-watch.js
    Original file line number Diff line number Diff line change
    @@ -5,8 +5,8 @@
    *
    * LEARN HOW TO USE IT:
    * http://watch.k6.com.br
    * DOWNLOAD:
    * https://gist.github.com/gists/1627705/download
    * FORK:
    * https://gist.github.com/1627705
    */

    Object.prototype.watch = function() {
    @@ -149,10 +149,10 @@ Object.prototype.attributes = function(){
    response = {};
    for (var prop2 in obj) {

    if(!obj[prop2] || isFunction(obj[prop2]) || prop2 == "watchers" || prop2 == "__proto__")
    if(obj[prop2]===undefined || isFunction(obj[prop2]) || prop2 == "watchers" || prop2 == "__proto__")
    continue;

    if(obj[prop2].attributes)
    if(obj[prop2] && obj[prop2].attributes)
    response[prop2] = obj[prop2].attributes();
    else
    response[prop2] = obj[prop2];
  15. @melanke melanke revised this gist Jan 27, 2012. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion object-watch.js
    Original file line number Diff line number Diff line change
    @@ -96,7 +96,7 @@ Object.prototype.watchOne = function(prop, watcher) {
    var oldvalAtr = oldval.attributes() || oldval;
    var newvalAtr = newval.attributes() || newval;

    if (JSON.stringify(oldvalAtr) != JSON.stringify(newvalAtr)) {
    if (JSON.stringify(oldvalAtr) != JSON.stringify(newvalAtr) && arguments.callee.caller != watcher) {
    obj.callWatchers(prop);
    }
    };
  16. @melanke melanke revised this gist Jan 23, 2012. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion object-watch.js
    Original file line number Diff line number Diff line change
    @@ -131,7 +131,7 @@ Object.prototype.attributes = function(){

    var response;

    if(obj instanceof String){
    if(obj instanceof Boolean || obj instanceof Number || obj instanceof String){
    return obj;
    }else if(Array.isArray(obj)){
    response = [];
  17. @melanke melanke revised this gist Jan 23, 2012. 1 changed file with 108 additions and 19 deletions.
    127 changes: 108 additions & 19 deletions object-watch.js
    Original file line number Diff line number Diff line change
    @@ -5,6 +5,8 @@
    *
    * LEARN HOW TO USE IT:
    * http://watch.k6.com.br
    * DOWNLOAD:
    * https://gist.github.com/gists/1627705/download
    */

    Object.prototype.watch = function() {
    @@ -114,25 +116,6 @@ Object.prototype.watchOne = function(prop, watcher) {

    };

    Object.prototype.watchFunctions = function(prop) {
    var obj = this;

    if (obj[prop] && obj[prop].push) {
    obj[prop].push = (function() { //arrays
    var original = Array.prototype.push;
    return function() {
    var response = original.apply(this, arguments);

    obj.watchOne(obj[prop]);
    obj.callWatchers(prop);

    return response;
    };
    })();
    }

    };

    Object.prototype.callWatchers = function(prop) {
    var obj = this;

    @@ -183,6 +166,112 @@ Object.prototype.attributes = function(){



    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]';
  18. @melanke melanke revised this gist Jan 23, 2012. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion object-watch.js
    Original file line number Diff line number Diff line change
    @@ -4,7 +4,7 @@
    * [email protected]
    *
    * LEARN HOW TO USE IT:
    * http://dl.dropbox.com/u/786375/watch/index.html
    * http://watch.k6.com.br
    */

    Object.prototype.watch = function() {
  19. @melanke melanke revised this gist Jan 20, 2012. 1 changed file with 2 additions and 21 deletions.
    23 changes: 2 additions & 21 deletions object-watch.js
    Original file line number Diff line number Diff line change
    @@ -3,27 +3,8 @@
    * GIL LOPES BUENO
    * [email protected]
    *
    * USAGE:
    *
    * object.watch(function(){
    * alert("some attribute of object has been changed");
    * });
    *
    * object.watch([
    * "attr1", "attr2"
    * ],
    * function(){
    * alert("attribute attr1 or attr2 of object has been changed");
    * });
    *
    * object.watch("attr1", function(){
    * alert("attribute attr1 of object has been changed");
    * });
    *
    * object.attr1 = "different value"; //will trigger all 3 functions declared before
    *
    * WORKS WITH ARRAYS TOO!
    * object.attr1.push("new item"); //will trigger all 3 functions declared before
    * LEARN HOW TO USE IT:
    * http://dl.dropbox.com/u/786375/watch/index.html
    */

    Object.prototype.watch = function() {
  20. @melanke melanke revised this gist Jan 20, 2012. 1 changed file with 186 additions and 121 deletions.
    307 changes: 186 additions & 121 deletions object-watch.js
    Original file line number Diff line number Diff line change
    @@ -21,129 +21,194 @@
    * });
    *
    * object.attr1 = "different value"; //will trigger all 3 functions declared before
    *
    * WORKS WITH ARRAYS TOO!
    * object.attr1.push("new item"); //will trigger all 3 functions declared before
    */

    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 props = [];
    for(var prop in this){
    if(!isFunction(this[prop]) && prop != "watchers" && prop != "__proto__")
    props.push(prop);
    }
    this.watchMany(props, watcher);
    };


    Object.prototype.watchMany = function(props, watcher){
    for(var prop in props){
    this.watchOne(props[prop], watcher);
    }
    };

    Object.prototype.watchOne = function(prop, watcher) {

    var obj = this;
    var val = obj[prop];

    if(typeof(obj[prop])=="object")
    obj[prop].watchAll(watcher);

    if(!obj.watchers){
    obj.watchers = {};
    }

    if(!obj.watchers[prop])
    obj.watchers[prop] = [];

    obj.watchers[prop].push(watcher);

    var getter = function() {
    return val;
    };


    var setter = function (newval) {
    var oldval = val;
    val = newval;


    if(typeof(obj[prop])=="object")
    obj[prop].watchAll(watcher);

    obj.watchArray(prop, watcher);


    if(oldval != newval){
    obj.callWatchers(prop);
    }
    };

    if(Object.defineProperty) { // ECMAScript 5
    Object.defineProperty(obj, prop, {
    get: getter,
    set: setter,
    enumerable: false,
    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);
    }

    obj.watchArray(prop, watcher);


    };

    Object.prototype.watchArray = function(prop, watcher) {

    var obj = this;

    if(obj[prop] && obj[prop].push){
    obj[prop].push=(function(){ //arrays
    var original = Array.prototype.push;
    return function() {
    original.apply(this,arguments);

    obj.callWatchers(prop);
    };
    })();
    }

    };

    Object.prototype.callWatchers = function(prop){

    for(var wr in obj.watchers[prop]){
    if(isInt(wr))
    obj.watchers[prop][wr]();
    }
    };


    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] || isFunction(obj[prop]) || prop == "watchers" || prop == "__proto__") //dont watch if it is null, is a function, named "watchers" or "__proto__"
    return;

    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;



    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();
    }
    if (JSON.stringify(oldvalAtr) != JSON.stringify(newvalAtr)) {
    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.watchFunctions = function(prop) {
    var obj = this;

    if (obj[prop] && obj[prop].push) {
    obj[prop].push = (function() { //arrays
    var original = Array.prototype.push;
    return function() {
    var response = original.apply(this, arguments);

    obj.watchOne(obj[prop]);
    obj.callWatchers(prop);

    return response;
    };
    })();
    }

    };

    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 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] || isFunction(obj[prop2]) || prop2 == "watchers" || prop2 == "__proto__")
    continue;

    if(obj[prop2].attributes)
    response[prop2] = obj[prop2].attributes();
    else
    response[prop2] = obj[prop2];
    }
    }else{
    return obj;
    }

    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();
    }
  21. @melanke melanke revised this gist Jan 19, 2012. 1 changed file with 11 additions and 9 deletions.
    20 changes: 11 additions & 9 deletions object-watch.js
    Original file line number Diff line number Diff line change
    @@ -87,10 +87,7 @@


    if(oldval != newval){
    for(var wr in obj.watchers[prop]){
    if(isInt(wr))
    obj.watchers[prop][wr]();
    }
    obj.callWatchers(prop);
    }
    };

    @@ -121,15 +118,20 @@
    return function() {
    original.apply(this,arguments);

    for(var wr in obj.watchers[prop]){
    if(isInt(wr))
    obj.watchers[prop][wr]();
    }
    obj.callWatchers(prop);
    };
    })();
    }

    }
    };

    Object.prototype.callWatchers = function(prop){

    for(var wr in obj.watchers[prop]){
    if(isInt(wr))
    obj.watchers[prop][wr]();
    }
    };



  22. @melanke melanke revised this gist Jan 19, 2012. 1 changed file with 19 additions and 2 deletions.
    21 changes: 19 additions & 2 deletions object-watch.js
    Original file line number Diff line number Diff line change
    @@ -79,6 +79,13 @@
    var oldval = val;
    val = newval;


    if(typeof(obj[prop])=="object")
    obj[prop].watchAll(watcher);

    obj.watchArray(prop, watcher);


    if(oldval != newval){
    for(var wr in obj.watchers[prop]){
    if(isInt(wr))
    @@ -98,8 +105,17 @@
    Object.prototype.__defineGetter__.call(obj, prop, getter);
    Object.prototype.__defineSetter__.call(obj, prop, setter);
    }

    obj.watchArray(prop, watcher);

    if(obj[prop]){

    };

    Object.prototype.watchArray = function(prop, watcher) {

    var obj = this;

    if(obj[prop] && obj[prop].push){
    obj[prop].push=(function(){ //arrays
    var original = Array.prototype.push;
    return function() {
    @@ -112,7 +128,8 @@
    };
    })();
    }
    };

    }



  23. @melanke melanke revised this gist Jan 19, 2012. 1 changed file with 19 additions and 7 deletions.
    26 changes: 19 additions & 7 deletions object-watch.js
    Original file line number Diff line number Diff line change
    @@ -5,26 +5,38 @@
    *
    * USAGE:
    *
    * object.watchAll(function(){
    * object.watch(function(){
    * alert("some attribute of object has been changed");
    * });
    *
    * object.watchMany([
    * object.watch([
    * "attr1", "attr2"
    * ],
    * function(){
    * alert("attribute attr1 or attr2 of object has been changed");
    * });
    *
    * object.watchOne("attr1", function(){
    * object.watch("attr1", function(){
    * alert("attribute attr1 of object has been changed");
    * });
    *
    * object.attr1 = "different value"; //will trigger a object.attr1 watch or object watchAll
    * object.attr1 = "different value"; //will trigger all 3 functions declared before
    * WORKS WITH ARRAYS TOO!
    * object.attr1.push("new item"); //will trigger a object.attr1 watch or object watchAll
    * object.attr1.push("new item"); //will trigger all 3 functions declared before
    */

    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 props = [];
    for(var prop in this){
    @@ -33,7 +45,7 @@
    }
    this.watchMany(props, watcher);
    };


    Object.prototype.watchMany = function(props, watcher){
    for(var prop in props){
    @@ -66,7 +78,7 @@
    var setter = function (newval) {
    var oldval = val;
    val = newval;

    if(oldval != newval){
    for(var wr in obj.watchers[prop]){
    if(isInt(wr))
  24. @melanke melanke revised this gist Jan 18, 2012. 1 changed file with 0 additions and 2 deletions.
    2 changes: 0 additions & 2 deletions object-watch.js
    Original file line number Diff line number Diff line change
    @@ -56,8 +56,6 @@
    if(!obj.watchers[prop])
    obj.watchers[prop] = [];

    console.log("WATCHER:");
    console.log(watcher);
    obj.watchers[prop].push(watcher);

    var getter = function() {
  25. @melanke melanke revised this gist Jan 18, 2012. 1 changed file with 20 additions and 7 deletions.
    27 changes: 20 additions & 7 deletions object-watch.js
    Original file line number Diff line number Diff line change
    @@ -33,12 +33,6 @@
    }
    this.watchMany(props, watcher);
    };


    function isFunction(functionToCheck) {
    var getType = {};
    return functionToCheck && getType.toString.call(functionToCheck) == '[object Function]';
    }


    Object.prototype.watchMany = function(props, watcher){
    @@ -62,6 +56,8 @@
    if(!obj.watchers[prop])
    obj.watchers[prop] = [];

    console.log("WATCHER:");
    console.log(watcher);
    obj.watchers[prop].push(watcher);

    var getter = function() {
    @@ -75,6 +71,7 @@

    if(oldval != newval){
    for(var wr in obj.watchers[prop]){
    if(isInt(wr))
    obj.watchers[prop][wr]();
    }
    }
    @@ -99,9 +96,25 @@
    original.apply(this,arguments);

    for(var wr in obj.watchers[prop]){
    if(isInt(wr))
    obj.watchers[prop][wr]();
    }
    };
    })();
    }
    };
    };





    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();
    }
  26. @melanke melanke revised this gist Jan 17, 2012. 1 changed file with 4 additions and 0 deletions.
    4 changes: 4 additions & 0 deletions object-watch.js
    Original file line number Diff line number Diff line change
    @@ -19,6 +19,10 @@
    * object.watchOne("attr1", function(){
    * alert("attribute attr1 of object has been changed");
    * });
    *
    * object.attr1 = "different value"; //will trigger a object.attr1 watch or object watchAll
    * WORKS WITH ARRAYS TOO!
    * object.attr1.push("new item"); //will trigger a object.attr1 watch or object watchAll
    */

    Object.prototype.watchAll = function(watcher){
  27. @melanke melanke revised this gist Jan 17, 2012. 1 changed file with 100 additions and 34 deletions.
    134 changes: 100 additions & 34 deletions object-watch.js
    Original file line number Diff line number Diff line change
    @@ -1,37 +1,103 @@
    // Cross-browser object.watch and object.unwatch

    // object.watch
    if (!Object.prototype.watch) {
    Object.prototype.watch = function (prop, handler) {
    var oldval = this[prop], newval = oldval,
    getter = function () {
    return newval;
    },
    setter = function (val) {
    oldval = newval;
    return newval = handler.call(this, prop, oldval, val);
    };
    if (delete this[prop]) { // can't watch constants
    if (Object.defineProperty) { // ECMAScript 5
    Object.defineProperty(this, prop, {
    get: getter,
    set: setter,
    enumerable: false,
    configurable: true
    });
    } else if (Object.prototype.__defineGetter__ && Object.prototype.__defineSetter__) { // legacy
    Object.prototype.__defineGetter__.call(this, prop, getter);
    Object.prototype.__defineSetter__.call(this, prop, setter);
    }
    /**
    * DEVELOPED BY
    * GIL LOPES BUENO
    * [email protected]
    *
    * USAGE:
    *
    * object.watchAll(function(){
    * alert("some attribute of object has been changed");
    * });
    *
    * object.watchMany([
    * "attr1", "attr2"
    * ],
    * function(){
    * alert("attribute attr1 or attr2 of object has been changed");
    * });
    *
    * object.watchOne("attr1", function(){
    * alert("attribute attr1 of object has been changed");
    * });
    */

    Object.prototype.watchAll = function(watcher){
    var props = [];
    for(var prop in this){
    if(!isFunction(this[prop]) && prop != "watchers" && prop != "__proto__")
    props.push(prop);
    }
    this.watchMany(props, watcher);
    };
    }

    // object.unwatch
    if (!Object.prototype.unwatch) {
    Object.prototype.unwatch = function (prop) {
    var val = this[prop];
    delete this[prop]; // remove accessors
    this[prop] = val;


    function isFunction(functionToCheck) {
    var getType = {};
    return functionToCheck && getType.toString.call(functionToCheck) == '[object Function]';
    }


    Object.prototype.watchMany = function(props, watcher){
    for(var prop in props){
    this.watchOne(props[prop], watcher);
    }
    };
    }

    Object.prototype.watchOne = function(prop, watcher) {

    var obj = this;
    var val = obj[prop];

    if(typeof(obj[prop])=="object")
    obj[prop].watchAll(watcher);

    if(!obj.watchers){
    obj.watchers = {};
    }

    if(!obj.watchers[prop])
    obj.watchers[prop] = [];

    obj.watchers[prop].push(watcher);

    var getter = function() {
    return val;
    };


    var setter = function (newval) {
    var oldval = val;
    val = newval;

    if(oldval != newval){
    for(var wr in obj.watchers[prop]){
    obj.watchers[prop][wr]();
    }
    }
    };

    if(Object.defineProperty) { // ECMAScript 5
    Object.defineProperty(obj, prop, {
    get: getter,
    set: setter,
    enumerable: false,
    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);
    }

    if(obj[prop]){
    obj[prop].push=(function(){ //arrays
    var original = Array.prototype.push;
    return function() {
    original.apply(this,arguments);

    for(var wr in obj.watchers[prop]){
    obj.watchers[prop][wr]();
    }
    };
    })();
    }
    };
  28. @eligrey eligrey revised this gist Sep 10, 2011. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion object-watch.js
    Original file line number Diff line number Diff line change
    @@ -16,7 +16,7 @@ if (!Object.prototype.watch) {
    Object.defineProperty(this, prop, {
    get: getter,
    set: setter,
    enumerable: true,
    enumerable: false,
    configurable: true
    });
    } else if (Object.prototype.__defineGetter__ && Object.prototype.__defineSetter__) { // legacy
  29. @eligrey eligrey revised this gist Apr 30, 2010. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions object-watch.js
    Original file line number Diff line number Diff line change
    @@ -12,14 +12,14 @@ if (!Object.prototype.watch) {
    return newval = handler.call(this, prop, oldval, val);
    };
    if (delete this[prop]) { // can't watch constants
    if (Object.defineProperty) // ECMAScript 5
    if (Object.defineProperty) { // ECMAScript 5
    Object.defineProperty(this, prop, {
    get: getter,
    set: setter,
    enumerable: true,
    configurable: true
    });
    else if (Object.prototype.__defineGetter__ && Object.prototype.__defineSetter__) { // legacy
    } else if (Object.prototype.__defineGetter__ && Object.prototype.__defineSetter__) { // legacy
    Object.prototype.__defineGetter__.call(this, prop, getter);
    Object.prototype.__defineSetter__.call(this, prop, setter);
    }
  30. @eligrey eligrey created this gist Apr 30, 2010.
    37 changes: 37 additions & 0 deletions object-watch.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,37 @@
    // Cross-browser object.watch and object.unwatch

    // object.watch
    if (!Object.prototype.watch) {
    Object.prototype.watch = function (prop, handler) {
    var oldval = this[prop], newval = oldval,
    getter = function () {
    return newval;
    },
    setter = function (val) {
    oldval = newval;
    return newval = handler.call(this, prop, oldval, val);
    };
    if (delete this[prop]) { // can't watch constants
    if (Object.defineProperty) // ECMAScript 5
    Object.defineProperty(this, prop, {
    get: getter,
    set: setter,
    enumerable: true,
    configurable: true
    });
    else if (Object.prototype.__defineGetter__ && Object.prototype.__defineSetter__) { // legacy
    Object.prototype.__defineGetter__.call(this, prop, getter);
    Object.prototype.__defineSetter__.call(this, prop, setter);
    }
    }
    };
    }

    // object.unwatch
    if (!Object.prototype.unwatch) {
    Object.prototype.unwatch = function (prop) {
    var val = this[prop];
    delete this[prop]; // remove accessors
    this[prop] = val;
    };
    }