1 define(function(require) {
5 var _ = require('libs/underscore'),
9 var getTransDesc = function(desc) {
10 if(typeof desc === 'function') {
14 throw new Error('Got transformation description without implementation.');
19 toret.createGenericTransformation = function(desc, name) {
20 desc = getTransDesc(desc);
22 var GenericTransformation = function(document, args) {
23 this.args = args || [];
24 var transformation = this;
26 var patchObject = function(obj, depth) {
27 depth = _.isNumber(depth) ? depth : 1;
31 _.keys(obj).forEach(function(key) {
35 transformation.wrapNodeProperty(obj, key);
36 } else if(_.isObject(value)) {
37 patchObject(value, depth+1);
43 this.args.forEach(function(arg, idx, args) {
45 if(arg.nodeType) { // ~
46 transformation.wrapNodeProperty(args, idx);
47 } else if(_.isObject(arg)) {
53 this.document = document;
59 _.extend(GenericTransformation.prototype, {
61 run: function(options) {
63 if(!desc.undo && options.beUndoable) {
64 changeRoot = this.getChangeRoot();
67 'Transformation {name} returned invalid change root value'
68 .replace('{name}', name)
71 this.changeRootPath = changeRoot.getPath();
72 this.snapshot = changeRoot.clone();
74 var argsToPass = desc.undo ? [this].concat(this.args) : this.args;
75 var toret = desc.impl.apply(this.context, argsToPass);
81 desc.undo.call(this.context, this);
83 this.document.getNodeByPath(this.changeRootPath).replaceWith(this.snapshot);
86 getChangeRoot: desc.getChangeRoot || function() {
87 return this.document.root;
89 wrapNodeProperty: function(object, propName, value) {
90 var transformation = this,
94 value = value || object[propName];
95 if(value && value.nodeType) {
96 path = value.getPath();
97 Object.defineProperty(object, propName, {
99 if((lastRunNumber !== transformation.runCount) && path) {
100 value = transformation.document.getNodeByPath(path);
101 lastRunNumber = transformation.runCount;
110 return GenericTransformation;
113 toret.createContextTransformation = function(desc, name) {
114 var GenericTransformation = toret.createGenericTransformation(desc, name);
116 var ContextTransformation = function(document, object, args) {
117 GenericTransformation.call(this, document, args);
119 if(document === object) {
120 this.context = document;
122 this.wrapNodeProperty(this, 'context', object);
125 ContextTransformation.prototype = Object.create(GenericTransformation.prototype);
126 return ContextTransformation;