smartxml: push transformation onto the undo stack only if it actually changed the...
authorAleksander Łukasz <aleksander.lukasz@nowoczesnapolska.org.pl>
Tue, 21 Jan 2014 11:13:25 +0000 (12:13 +0100)
committerAleksander Łukasz <aleksander.lukasz@nowoczesnapolska.org.pl>
Tue, 21 Jan 2014 11:36:17 +0000 (12:36 +0100)
At least one change event must be emmited during transformation for
a document to be considered changed.

src/smartxml/smartxml.js
src/smartxml/smartxml.test.js

index d168e6d..8bf531b 100644 (file)
@@ -441,6 +441,27 @@ $.extend(Document.prototype, Backbone.Events, {
         });
     },
 
+    ifChanged: function(context, action, documentChangedHandler, documentUnchangedHandler) {
+        var hasChanged = false,
+            changeMonitor = function() {
+                hasChanged = true;
+            };
+
+        this.on('change', changeMonitor);
+        action.call(context);
+        this.off('change', changeMonitor);
+        
+        if(hasChanged) {
+            if(documentChangedHandler) {
+                documentChangedHandler.call(context);
+            }
+        } else {
+            if(documentUnchangedHandler) {
+                documentUnchangedHandler.call(context);
+            }
+        }
+    },
+
     transform: function(Transformation, args) {
         var toret, transformation;
 
@@ -451,17 +472,26 @@ $.extend(Document.prototype, Backbone.Events, {
         }
         if(transformation) {
             this._transformationLevel++;
-            toret = transformation.run({beUndoable:this._transformationLevel === 1});
-            if(this._transformationLevel === 1 && !this._undoInProgress) {
-                if(this._transactionInProgress) {
-                    this._transactionStack.push(transformation);
-                } else {
-                    this.undoStack.push(transformation);
+            
+            this.ifChanged(
+                this,
+                function() {
+                    toret = transformation.run({beUndoable:this._transformationLevel === 1});
+                },
+                function() {
+                    if(this._transformationLevel === 1 && !this._undoInProgress) {
+                        if(this._transactionInProgress) {
+                            this._transactionStack.push(transformation);
+                        } else {
+                            this.undoStack.push(transformation);
+                        }
+                    }
+                    if(!this._undoInProgress && this._transformationLevel === 1) {
+                        this.redoStack = [];
+                    }
                 }
-            }
-            if(!this._undoInProgress && this._transformationLevel === 1) {
-                this.redoStack = [];
-            }
+            );
+
             this._transformationLevel--;
             return toret;
         } else {
index 0883ba7..e6f0baa 100644 (file)
@@ -1139,6 +1139,7 @@ describe('smartxml', function() {
         
         var sampleMethod = function(val) {
             this._$.attr('x', val);
+            this.triggerChangeEvent();
         };
 
         var transformations = {
@@ -1235,10 +1236,12 @@ describe('smartxml', function() {
             doc.registerExtension({elementNode: {transformations: {
                 nested: function(v) {
                     this._$.attr('innerAttr', v);
+                    this.triggerChangeEvent();
                 },
                 outer: function(v) {
                     this.nested(v);
                     this._$.attr('outerAttr', v);
+                    this.triggerChangeEvent();
                 }
             }}});
 
@@ -1270,6 +1273,20 @@ describe('smartxml', function() {
 
         });
 
+        it('ignores transformation if document didn\'t emit change event', function() {
+            var doc = getDocumentFromXML('<div></div>');
+
+            doc.registerExtension({elementNode: {transformations: {
+                test: function() {
+                    // empty
+                }
+            }}});
+
+            doc.root.test();
+            expect(doc.undoStack.length).to.equal(0);
+
+        });
+
         describe('Transactions', function() {
             it('allows to undo/redo series of transformations at once', function() {
                 var doc = getDocumentFromXML('<div></div>');
@@ -1314,14 +1331,17 @@ describe('smartxml', function() {
                     elementNode: {transformations: {
                         unaware: function(v) {
                             this.setAttr('unware', v);
+                            this.triggerChangeEvent();
                         },
                         smart: {
                             impl: function(t, v) {
                                 t.oldVal = this.getAttr('smart');
                                 this.setAttr('smart', v);
+                                this.triggerChangeEvent();
                             },
                             undo: function(t) {
                                 this.setAttr('smart', t.oldVal);
+                                this.triggerChangeEvent();
                             }
                         }
                     }}