From 295c9ced8e77df8e0d83951159d3c3c416771753 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Aleksander=20=C5=81ukasz?= Date: Tue, 21 Jan 2014 12:13:25 +0100 Subject: [PATCH] smartxml: push transformation onto the undo stack only if it actually changed the document At least one change event must be emmited during transformation for a document to be considered changed. --- src/smartxml/smartxml.js | 50 ++++++++++++++++++++++++++++------- src/smartxml/smartxml.test.js | 20 ++++++++++++++ 2 files changed, 60 insertions(+), 10 deletions(-) diff --git a/src/smartxml/smartxml.js b/src/smartxml/smartxml.js index d168e6d..8bf531b 100644 --- a/src/smartxml/smartxml.js +++ b/src/smartxml/smartxml.js @@ -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 { diff --git a/src/smartxml/smartxml.test.js b/src/smartxml/smartxml.test.js index 0883ba7..e6f0baa 100644 --- a/src/smartxml/smartxml.test.js +++ b/src/smartxml/smartxml.test.js @@ -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('
'); + + 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('
'); @@ -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(); } } }} -- 2.20.1