var _ = require('libs/underscore'),
toret = {};
+
var getTransDesc = function(desc) {
if(typeof desc === 'function') {
desc = {impl: desc};
var GenericTransformation = function(document, args) {
this.args = args || [];
-
var transformation = this;
- // _.keys(this.args).forEach(function(key) {
- // if(transformation.args[key].nodeType) { //@@ change to instanceof check, fix circular dependency
- // var value = transformation.args[key],
- // path = value.getPath();
- // Object.defineProperty(transformation.args, key, {
- // get: function() {
- // if(transformation.hasRun) {
- // //console.log('returning via path');
- // return transformation.document.getNodeByPath(path);
- // } else {
- // //console.log('returning original arg');
- // return value;
-
- // }
- // }
- // });
- // }
- // });
-
- // potem spr na dotychczasowych undo/redo tests;
+ var patchObject = function(obj, depth) {
+ depth = _.isNumber(depth) ? depth : 1;
+ if(depth > 3) {
+ return;
+ }
+ _.keys(obj).forEach(function(key) {
+ var value = obj[key];
+ if(value) {
+ if(value.nodeType) {
+ transformation.wrapNodeProperty(obj, key);
+ } else if(_.isObject(value)) {
+ patchObject(value, depth+1);
+ }
+ }
+ });
+ };
this.args.forEach(function(arg, idx, args) {
- var path;
if(arg) {
if(arg.nodeType) { // ~
- path = arg.getPath();
- Object.defineProperty(args, idx, {
- get: function() {
- if(transformation.hasRun && path) {
- return transformation.document.getNodeByPath(path);
- } else {
- return arg;
- }
- }
- });
+ transformation.wrapNodeProperty(args, idx);
} else if(_.isObject(arg)) {
- _.keys(arg).forEach(function(key) {
- var value = arg[key],
- path;
- if(value && value.nodeType) {
- path = value.getPath();
- Object.defineProperty(arg, key, {
- get: function() {
- if(transformation.hasRun && path) {
- return transformation.document.getNodeByPath(path);
- } else {
- return value;
- }
- }
- });
- }
- });
+ patchObject(arg);
}
}
});
this.document = document;
- this.hasRun = false;
+ this.runCount = 0;
if(desc.init) {
desc.init.call(this);
}
run: function(options) {
var changeRoot;
if(!desc.undo && options.beUndoable) {
- changeRoot = desc.getChangeRoot ? desc.getChangeRoot.call(this) : this.document.root;
- this.snapshot = changeRoot.clone();
+ changeRoot = this.getChangeRoot();
+ if(!changeRoot) {
+ throw new Error(
+ 'Transformation {name} returned invalid change root value'
+ .replace('{name}', name)
+ );
+ }
this.changeRootPath = changeRoot.getPath();
+ this.snapshot = changeRoot.clone();
}
var argsToPass = desc.undo ? [this].concat(this.args) : this.args;
var toret = desc.impl.apply(this.context, argsToPass);
- this.hasRun = true;
+ this.runCount++;
return toret;
},
undo: function() {
this.document.getNodeByPath(this.changeRootPath).replaceWith(this.snapshot);
}
},
+ getChangeRoot: desc.getChangeRoot || function() {
+ return this.document.root;
+ },
+ wrapNodeProperty: function(object, propName, value) {
+ var transformation = this,
+ lastRunNumber = 0,
+ path;
+
+ value = value || object[propName];
+ if(value && value.nodeType) {
+ path = value.getPath();
+ Object.defineProperty(object, propName, {
+ get: function() {
+ if((lastRunNumber !== transformation.runCount) && path) {
+ value = transformation.document.getNodeByPath(path);
+ lastRunNumber = transformation.runCount;
+ }
+ return value;
+ }
+ });
+ }
+ }
});
return GenericTransformation;
if(document === object) {
this.context = document;
} else {
- var contextPath = object.getPath(),
- transformation = this;
- Object.defineProperty(this, 'context', {
- get: function() {
- if(transformation.hasRun) {
- return transformation.document.getNodeByPath(contextPath);
- } else {
- return object;
- }
- }
- });
+ this.wrapNodeProperty(this, 'context', object);
}
};
ContextTransformation.prototype = Object.create(GenericTransformation.prototype);