X-Git-Url: https://git.mdrn.pl/fnpeditor.git/blobdiff_plain/21cd91531dd9c6e88d00da03f6b2f3ad88fb0da0..3dfe15d50b60598341b9754876db4a48162c5cd0:/src/smartxml/transformations.js diff --git a/src/smartxml/transformations.js b/src/smartxml/transformations.js index 25c0ec1..4a8e5a8 100644 --- a/src/smartxml/transformations.js +++ b/src/smartxml/transformations.js @@ -5,6 +5,7 @@ define(function(require) { var _ = require('libs/underscore'), toret = {}; + var getTransDesc = function(desc) { if(typeof desc === 'function') { desc = {impl: desc}; @@ -20,67 +21,37 @@ toret.createGenericTransformation = function(desc, name) { 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); } @@ -90,22 +61,51 @@ toret.createGenericTransformation = function(desc, name) { 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() { if(desc.undo) { desc.undo.call(this.context, this); + this.runCount++; } else { 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; @@ -120,17 +120,7 @@ toret.createContextTransformation = function(desc, name) { 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);