About
Watch.JS is a small library with a lot of possibilities. You may know that the "Observer" design pattern involves executing some function when an observed object changes. Other libraries exist that do this, but with Watch.JS you will not have to change the way you develop. Take a look at the examples to see how simple it is to add Watch.JS to your code.
Compatible with all serious browsers :P
Works with: IE 9+, FF 4+, SF 5+, WebKit, CH 7+, OP 12+, BESEN, Node.JS , Rhino 1.7+
Installing
HTML Script TAG
<script src="watch.js" type="text/javascript"></script>
Via NPM
npm install melanke-watchjs
Importing
Import as ECMA2015 module
import WatchJS from 'melanke-watchjs';
var watch = WatchJS.watch;
var unwatch = WatchJS.unwatch;
var callWatchers = WatchJS.callWatchers;
Require
var WatchJS = require("melanke-watchjs")
var watch = WatchJS.watch;
var unwatch = WatchJS.unwatch;
var callWatchers = WatchJS.callWatchers;
RequireJS
require("watch", function(WatchJS){
var watch = WatchJS.watch;
var unwatch = WatchJS.unwatch;
var callWatchers = WatchJS.callWatchers;
});
Examples
Observe the changes of one object attribute
var ex1 = {
attr1: "initial value of attr1",
attr2: "initial value of attr2"
};
watch(ex1, "attr1", function(){
alert("attr1 changed!");
});
ex1.attr1 = "other value";
Try out
Observe the changes of more than one object attribute
var ex2 = {
attr1: 0,
attr2: 0,
attr3: 0
};
watch(ex2, ["attr2", "attr3"], function(){
alert("attr2 or attr3 changed!");
});
ex2.attr2 = 50;
Try out
Observe the changes of all attributes of the object
var ex3 = {
attr1: 0,
attr2: "initial value of attr2",
attr3: ["a", 3, null]
};
watch(ex3, function(){
alert("some attribute of ex3 changes!");
});
ex3.attr3.push("new value");
Try out
Remove a Watcher
var obj = {
phrase: "hey",
name: "buddy",
alert: function(){
alert(obj.phrase + " " + obj.name);
},
alert2: function(){
alert(obj.name + ", " + obj.phrase);
}
}
watch(obj, "name", obj.alert);
watch(obj, "name", obj.alert2);
obj.name = "johnny";
unwatch(obj, "name", obj.alert);
obj.name = "phil";
Try out
More information about the change
var ex1 = {
attr1: "initial value of attr1",
attr2: "initial value of attr2"
};
watch(ex1, "attr1", function(prop, action, newvalue, oldvalue){
alert(prop+" - action: "+action+" - new: "+newvalue+", old: "+oldvalue+"... and the context: "+JSON.stringify(this));
});
ex1.attr1 = "other value";
Try out
Don't worry about the Infinite Loop
If you don't want to call a second watcher in the current scope just set WatchJS.noMore to true and it will be reset to false when this watcher finishes.
var ex1 = {
attr1: "inicial value of attr1",
attr2: "initial value of attr2"
};
watch(ex1, "attr1", function(){
WatchJS.noMore = true;
ex1.attr2 = ex1.attr1 + " + 1";
});
watch(ex1, "attr2", function(){
alert("attr2 changed");
});
ex1.attr1 = "other value to 1";
Try out
How deep you wanna go? Provide a level of children
var ex = {
l1a: "bla bla",
l1b: {
l2a: "lo lo",
l2b: {
deeper: "so deep"
}
}
};
watch(ex, function(){
alert("ex changed at lvl 2 or less");
}, 1);
watch(ex, function(){
alert("ex changed at lvl 3 or less");
}, 2);
ex.l1b.l2b.deeper = "other value";
ex.l1b.l2b = "other value";
Try out
By default new attributes will be ignored
After declaring a watcher for some object, when you add new attributes to this object and/or change it, the watcher will not be invoked.
var ex6 = {
attr1: 0,
attr2: 1
};
watch(ex6, function(){
alert("some attribute of ex6 changed!")
});
ex6.attr3 = null;
ex6.attr3 = "value";
Try out
Do you want to know when new attributes change too?
Well this is not perfect, you may have to wait 50 miliseconds
var ex = {
l1a: "bla bla",
l1b: {
l2a: "lo lo",
l2b: "hey hey"
}
};
watch(ex, function (prop, action, difference, oldvalue){
alert("prop: "+prop+"\n action: "+action+"\n difference: "+JSON.stringify(difference)+"\n old: "+JSON.stringify(oldvalue)+"\n ... and the context: "+JSON.stringify(this));
}, 0, true);
ex.l1b.l2c = "new attr";
setTimeout(function(){
ex.l1b.l2c = "other value";
}, 100);
Try out
Invoke the watcher anytime you want
var ex7 = {
attr1: 0,
attr2: 1
};
watch(ex7, function(){
alert("some attribute of ex6 changed!")
});
callWatchers(ex7, "attr1");
Try out
Compatible with JQuery
$(function(){
var obj = {cont: 0};
watch(obj, "cont", function(){
alert("obj.cont = "+obj.cont);
});
$("#button").click(function(){
obj.cont++;
});
});
Try out
Different ways to build Classes/Objects and use Watch.JS
var Apple = function(type) {
var _thisApple = this;
this.type = type;
this.color = "red";
this.getInfo = function() {
return this.color + ' ' + this.type + ' apple';
};
watch(this, function(){
console.log("although we are using Watch.js the apple structure remains the same");
for(var i in _thisApple){
console.log(i+": "+_thisApple[i]);
}
});
};
var apple = new Apple("macintosh");
apple.type = "other";
var Banana = function(type) {
var _thisBanana = this;
this.type = type;
this.color = "yellow";
watch(this, function(){
console.log("although we are using Watch.js the banana structure remains the same");
for(var i in _thisBanana){
console.log(i+": "+_thisBanana[i]);
}
});
};
Banana.prototype.getInfo = function() {
return this.color + ' ' + this.type + ' banana';
};
var banana = new Banana("Cavendish");
banana.type = "other";
var orange = {
type: "pocan",
color: "orange",
getInfo: function () {
return this.color + ' ' + this.type + ' apple';
}
};
watch(orange, function(){
console.log("although we are using Watch.js the orange structure remains the same");
for(var i in orange){
console.log(i+": "+orange[i]);
}
});
orange.type = "other";
Try out