X-Git-Url: https://git.mdrn.pl/fnpeditor.git/blobdiff_plain/2fbd2cb6926b1066b38adf0698a3679d089ad80c..588d7e070dc10575a1c4dc3cba3b7c777142617b:/src/smartxml/transformations.js diff --git a/src/smartxml/transformations.js b/src/smartxml/transformations.js index 6d72049..053ed10 100644 --- a/src/smartxml/transformations.js +++ b/src/smartxml/transformations.js @@ -5,31 +5,80 @@ define(function(require) { var _ = require('libs/underscore'), toret = {}; +var getTransDesc = function(desc) { + if(typeof desc === 'function') { + desc = {impl: desc}; + } + if(!desc.impl) { + throw new Error('Got transformation description without implementation.'); + } + return desc; +}; -toret.createGenericTransformation = function(desc) { +toret.createGenericTransformation = function(desc, name) { + desc = getTransDesc(desc); var GenericTransformation = function(document, args) { - this.args = 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; - + // _.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; + + + 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; + } } - } - }); + }); + } 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; + } + } + }); + } + }); + } } }); + this.document = document; this.hasRun = false; if(desc.init) { @@ -37,107 +86,66 @@ toret.createGenericTransformation = function(desc) { } }; _.extend(GenericTransformation.prototype, { - name: desc.name, - run: function() { + name: name, + run: function(options) { var changeRoot; - if(!desc.undo) { - changeRoot = desc.getChangeRoot ? desc.getChangeRoot.call(this) : this.document.root; - this.snapshot = changeRoot.clone(); + if(!desc.undo && options.beUndoable) { + 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 toret = desc.impl.call(this.context, this.args); // a argumenty do metody? + var argsToPass = desc.undo ? [this].concat(this.args) : this.args; + var toret = desc.impl.apply(this.context, argsToPass); this.hasRun = true; return toret; }, undo: function() { if(desc.undo) { - desc.undo.call(this.context); + desc.undo.call(this.context, this); } else { this.document.getNodeByPath(this.changeRootPath).replaceWith(this.snapshot); } }, + getChangeRoot: desc.getChangeRoot || function() { + return this.document.root; + } }); return GenericTransformation; }; -// var T = createGenericTransformation({impl: function() {}}); -// var t = T(doc, {a:1,b:2,c3:3}); - -toret.createContextTransformation = function(desc) { - // mozna sie pozbyc przez przeniesienie object/context na koniec argumentow konstruktora generic transformation - var GenericTransformation = toret.createGenericTransformation(desc); +toret.createContextTransformation = function(desc, name) { + var GenericTransformation = toret.createGenericTransformation(desc, name); var ContextTransformation = function(document, object, args) { GenericTransformation.call(this, document, args); if(document === object) { this.context = document; - } else { - var contextPath = object.getPath(); + } else { + var contextPath = object.getPath(), + transformation = this; Object.defineProperty(this, 'context', { get: function() { - // todo: to jakos inaczej, bo np. this.context w undo transformacji before to juz nie ten sam obiekt - // moze transformacja powinna zwracac zmodyfikowana sciezke do obiektu po dzialaniu run? - - // tu tez trick z hasRun - return document.getNodeByPath(contextPath); + if(transformation.hasRun) { + return transformation.document.getNodeByPath(contextPath); + } else { + return object; + } } }); } - } + }; ContextTransformation.prototype = Object.create(GenericTransformation.prototype); return ContextTransformation; -} -// var T = createContextTransformation({impl: function() {}}); -// var t = T(doc, node, {a:1,b:2,c3:3}); -/// - - - -toret.TransformationStorage = function() { - this._transformations = {}; }; -_.extend(toret.TransformationStorage.prototype, { - - register: function(Transformation) { - var list = (this._transformations[Transformation.prototype.name] = this._transformations[Transformation.prototype.name] || []); - list.push(Transformation); - }, - - get: function(name) { - var transformations = this._transformations[name]; - if(!transformations) { - throw new Error('Transformation "' + name + '" not found!'); - } - // na razie zwraca pierwsza - return transformations[0]; - } -}); - - - -// var registerTransformationFromMethod = (object, methodName, desc) { -// if(!object[methodName]) { -// throw new Exeption('Cannot register transformation from unknown method ' + methodName + ' on ' + object); -// } -// desc.impl = object[name]; -// Transformation = createContextTransformation(desc); -// object.prototype.registerContextTransformation(name, createContextTransformation(method)); -// }; - - -// registerTransformationFromMethod(ElementNode, 'setAttr', { -// impl: function(args) { -// this.setAttr(args.name, args.value); -// }, -// getChangeRoot: function() { -// return this.context; -// } - -// }); - return toret; }); \ No newline at end of file