Apr 18 2016

Dirty detection of a multi-dimentional javascript object

Category: Deverm @ 1:44 pm

I’m not sure what to call this.  It’s a proxy handler that watches the dirty state of an object.  I don’t know why, but I’m kinda proud of this.  It also has the ability to ignore fields.  The main goal is to have a mechanism to indicate if you should save an object or not.  In other words:

if (obj.dirty) { save(obj); }

window.objHandler = {
    dirty: false,
    ignore: [],
    get: function(target, name) {
        if (name != "dirty" && name != "ignore") {
            return name in target ? target[name] : undefined;
        }
        if (name == "ignore") {
            return this.ignore;
        }
        if (name == "dirty") {
            // console.log("get dirty:", target);
            if (this.dirty) {
                return true;
            }
            if (typeof target == "object") {
                if (target.dirty) {
                    return true;
                }
                for (k in target) {
                  if (typeof target[k] == "object" && target[k].dirty) {
                      return true;
                  }
                }
            }
            return this.dirty;
        }
        return undefined;
    },
    set: function(target, name, value) {
        if (name == "dirty") {
            this.dirty = value;
            if (typeof target == "object") {
                for (k in target) {
                    if (typeof target[k] == "object") {
                        target[k].dirty = value;
                    }
                }
            }
            return;
        }
        if (name == "ignore") {
            this.ignore = value;
            return;
        }
        if (angular.equals(target[name], value)) {
            return;
        }
        if (this.ignore.indexOf(name) == -1) {
            this.dirty = true;
        }
        var _type = typeof value;
        if (_type == "object") {
            // console.log("making proxy:", value);
            value = new Proxy(value, window.objHandler);
            value.dirty = true;
        }
        target[name] = value;
    }
};

var p = new Proxy({}, window.objHandler);
p.obj = {"foo":"bar"};
if (!p.dirty) {
    console.log("FAIL", "!p.dirty", "p should be dirty because obj was set");
}
if (!p.obj.dirty) {
    console.log("FAIL", "!p.obj.dirty", "p.obj should be dirty because it's new?");
}
p.obj.dirty = false;
if (p.obj.dirty) {
    console.log("FAIL", "p.obj.dirty", "Shouldn't be dirty because p.obj.dirty = false;");
}
if (p.dirty) {
    console.log("FAIL", "p.dirty", "Should still be dirty p.obj.dirty = false;");
}
p.dirty = false;
if (p.dirty) {
    console.log("FAIL", "p.dirty", "Should be clean");
}
p.obj.foo = "baz";
if(!p.dirty) {
    console.log("FAIL", "p.dirty should be true");
}

if (!p.obj.dirty) {
    console.log("FAIL", "p.obj.dirty should be true");
}
p.dirty = false;
if(p.obj.dirty) {
    console.log("FAIL", "p.obj.dirty should not be dirty");
}



console.log("p.dirty:",p.dirty);
console.log("p.obj.dirty", p.obj.dirty);
p.str = "string value";
p.integer = 1;
p.dec = 1.1;
console.log(JSON.stringify(p,null, "\t"));
console.log("p.dirty", p.dirty);
p.dirty = false;

 

 

Output:

p.dirty: false
p.obj.dirty false
{
	"obj": {
		"foo": "baz"
	},
	"str": "string value",
	"integer": 1,
	"dec": 1.1
}
p.dirty true

Leave a Reply

You must be logged in to post a comment. Login now.