cleanup
[fnpeditor.git] / src / smartxml / smartxml.js
index 8110a97..d912904 100644 (file)
@@ -38,8 +38,6 @@ var DocumentNode = function(nativeNode, document) {
 
 $.extend(DocumentNode.prototype, {
 
-    transformations: new transformations.TransformationStorage(),
-
     transform: function(name, args) {
         var Transformation = this.transformations.get(name),
             transformation;
@@ -382,63 +380,6 @@ $.extend(ElementNode.prototype, {
     }
 });
 
-// trans
-
-// todo - split+append
-
-ElementNode.prototype.transformations.register(transformations.createContextTransformation({
-    name: 'smartxml.setAttr',
-    impl: function(args) {
-        this.setAttr(args.name, args.value);
-    },
-    getChangeRoot: function() {
-        return this.context;
-    }
-}));
-
-ElementNode.prototype.transformations.register(transformations.createContextTransformation({
-    name: 'smartxml.setAttr2',
-    impl: function(args) {
-        this.prevAttr = this.getAttr(args.name);
-        this.setAttr(args.name, args.value);
-    },
-    undo: function(args) {
-        this.setAttr(args.name, this.prevAttr);
-    }
-}));
-
-DocumentNode.prototype.transformations.register(transformations.createContextTransformation({
-    name: 'smartxml.wrapWith',
-    getChangeRoot: function() {
-        return this.context.parent();
-    },
-    impl: function(args) {
-        return this.wrapWith(args);
-    }
-}));
-
-DocumentNode.prototype.transformations.register(transformations.createContextTransformation({
-    name: 'smartxml.wrapText',
-    getChangeRoot: function() {
-        return this.context;
-    },
-    impl: function(args) {
-        return this.wrapText(args);
-    }
-}));
-
-DocumentNode.prototype.transformations.register(transformations.createContextTransformation({
-    name: 'smartxml.detach',
-    getChangeRoot: function() {
-        return this.context.parent();
-    },
-    impl: function(args) {
-        return this.detach();
-    }
-}));
-
-///
-
 var TextNode = function(nativeNode, document) {
     DocumentNode.call(this, nativeNode, document);
 };
@@ -526,70 +467,40 @@ $.extend(TextNode.prototype, {
 });
 
 
-TextNode.prototype.transformations.register(transformations.createContextTransformation({
-    name: 'rng.breakContent',
-    // impl: function(args) {
-    //     var node = this.context,
-    //         newNodes, emptyNode, emptyText;
-    //     newNodes = node.transform('smartxml.split', {offset: args.offset});
-    //     [newNodes.first, newNodes.second].some(function(newNode) {
-    //         if(!(newNode.contents().length)) {
-    //             newNode.transform('smartxml.append', {text: ''});
-    //             return true; // break
-    //         }
-    //     });
-    //     return _.extend(newNodes, {emptyText: emptyText});
-    // },
-    impl: function(args) {
-        var node = this,
-            newNodes, emptyNode, emptyText;
-        newNodes = node.split({offset: args.offset});
-        [newNodes.first, newNodes.second].some(function(newNode) {
-            if(!(newNode.contents().length)) {
-                newNode.append({text: ''});
-                return true; // break
-            }
-        });
-        return _.extend(newNodes, {emptyText: emptyText});
-    },
-    getChangeRoot: function() {
-        return this.context.parent().parent();
-    },
-    isAllowed: function(args) {
-        var parent = this.parent();
-        return !!(parent && parent.parent());
-    }
-}));
+var parseXML = function(xml) {
+    return $($.trim(xml))[0];
+};
 
+var registerTransformation = function(desc, name, target) {
+    var Transformation = transformations.createContextTransformation(desc, name);
+    target.register(Transformation);
+};
 
-ElementNode.prototype.transformations.register(transformations.createContextTransformation({
-    name: 'smartxml.setText',
-    impl: function(args) {
-        this.setText(args.text);
-    },
-    getChangeRoot: function() {
-        return this.context;
+var registerMethod = function(methodName, method, target) {
+    if(target[methodName]) {
+        throw new Error('Cannot extend {target} with method name {methodName}. Name already exists.'
+            .replace('{target}', target)
+            .replace('{methodName}', methodName)
+        );
     }
-}));
-
-
-var parseXML = function(xml) {
-    return $($.trim(xml))[0];
+    target[methodName] = method;
 };
 
+
 var Document = function(xml) {
     this.loadXML(xml);
     this.undoStack = [];
     this.redoStack = [];
     this._transformationLevel = 0;
     this.transformations = new transformations.TransformationStorage();
-
+    
+    this._nodeMethods = {};
+    this._nodeTransformations = new transformations.TransformationStorage();
 };
 
 $.extend(Document.prototype, Backbone.Events, {
     ElementNodeFactory: ElementNode,
     TextNodeFactory: TextNode,
-    transformations: new transformations.TransformationStorage(),
 
     createDocumentNode: function(from) {
         if(!(from instanceof Node)) {
@@ -612,7 +523,10 @@ $.extend(Document.prototype, Backbone.Events, {
         } else if(from.nodeType === Node.ELEMENT_NODE) {
             Factory = this.ElementNodeFactory;
         }
-        return new Factory(from, this);
+        var toret = new Factory(from, this);
+        _.extend(toret, this._nodeMethods);
+        toret.transformations = this._nodeTransformations;
+        return toret;
     },
 
     loadXML: function(xml, options) {
@@ -761,6 +675,54 @@ $.extend(Document.prototype, Backbone.Events, {
         return insertion.ofNode;
     },
 
+    registerMethod: function(methodName, method) {
+        registerMethod(methodName, method, this);
+    },
+
+    registerNodeMethod: function(methodName, method) {
+        registerMethod(methodName, method, this._nodeMethods);
+    },
+
+    registerDocumentTransformation: function(desc, name) {
+        registerTransformation(desc, name, this.transformations);
+    },
+
+    registerNodeTransformation: function(desc, name) {
+        registerTransformation(desc, name, this._nodeTransformations);
+    },
+
+    registerExtension: function(extension) {
+        //debugger;
+        var doc = this,
+            existingPropertyNames = _.values(this);
+
+        ['document', 'documentNode'].forEach(function(dstName) {
+            var dstExtension = extension[dstName];
+            if(dstExtension) {
+                if(dstExtension.methods) {
+                    _.pairs(dstExtension.methods).forEach(function(pair) {
+                        var methodName = pair[0],
+                            method = pair[1],
+                            operation;
+                        operation = {document: 'registerMethod', documentNode: 'registerNodeMethod'}[dstName];
+                        doc[operation](methodName, method);
+
+                    });
+                }
+
+                if(dstExtension.transformations) {
+                    _.pairs(dstExtension.transformations).forEach(function(pair) {
+                        var name = pair[0],
+                            desc = pair[1],
+                            operation;
+                        operation = {document: 'registerDocumentTransformation', documentNode: 'registerNodeTransformation'}[dstName];
+                        doc[operation](desc, name);
+                    });
+                }
+            }
+        });
+    },
+
     transform: function(transformation, args) {
         //console.log('transform');
         var Transformation, toret;
@@ -817,20 +779,6 @@ var defineDocumentProperties = function(doc, $document) {
     }, configurable: true});
 };
 
-Document.prototype.transformations.register(transformations.createContextTransformation({
-    name: 'smartxml.wrapNodes',
-    // init: function() {
-
-    // },
-    // getChangeRoot: function() {
-    //     return this.context;
-    // },
-    impl: function(args) {
-        this.wrapNodes(args);
-    },
-
-}));
-
 
 return {
     documentFromXML: function(xml) {