diff --git a/js/id/core/history.js b/js/id/core/history.js index 87c9b0075..f4922d7cd 100644 --- a/js/id/core/history.js +++ b/js/id/core/history.js @@ -77,6 +77,21 @@ iD.History = function(context) { } }, + // Same as calling pop and then perform + overwrite: function() { + var previous = stack[index].graph; + + if (index > 0) { + index--; + stack.pop(); + } + stack = stack.slice(0, index + 1); + stack.push(perform(arguments)); + index++; + + return change(previous); + }, + undo: function() { var previous = stack[index].graph; diff --git a/js/id/id.js b/js/id/id.js index d9546502d..03702711c 100644 --- a/js/id/id.js +++ b/js/id/id.js @@ -126,6 +126,7 @@ window.iD = function () { context.perform = withDebouncedSave(history.perform); context.replace = withDebouncedSave(history.replace); context.pop = withDebouncedSave(history.pop); + context.overwrite = withDebouncedSave(history.overwrite); context.undo = withDebouncedSave(history.undo); context.redo = withDebouncedSave(history.redo); diff --git a/test/spec/core/history.js b/test/spec/core/history.js index f46907f21..d8be41a63 100644 --- a/test/spec/core/history.js +++ b/test/spec/core/history.js @@ -122,6 +122,49 @@ describe("iD.History", function () { }); }); + describe("#overwrite", function () { + it("returns a difference", function () { + history.perform(action, "annotation"); + expect(history.overwrite(action).changes()).to.eql({}); + }); + + it("updates the graph", function () { + history.perform(action, "annotation"); + var node = iD.Node(); + history.overwrite(function (graph) { return graph.replace(node); }); + expect(history.graph().entity(node.id)).to.equal(node); + }); + + it("replaces the undo annotation", function () { + history.perform(action, "annotation1"); + history.overwrite(action, "annotation2"); + expect(history.undoAnnotation()).to.equal("annotation2"); + }); + + it("does not push the redo stack", function () { + history.perform(action, "annotation"); + history.overwrite(action, "annotation2"); + expect(history.redoAnnotation()).to.be.undefined; + }); + + it("emits a change event", function () { + history.perform(action, "annotation"); + history.on('change', spy); + var difference = history.overwrite(action, "annotation2"); + expect(spy).to.have.been.calledWith(difference); + }); + + it("performs multiple actions", function () { + var action1 = sinon.stub().returns(iD.Graph()), + action2 = sinon.stub().returns(iD.Graph()); + history.perform(action, "annotation"); + history.overwrite(action1, action2, "annotation2"); + expect(action1).to.have.been.called; + expect(action2).to.have.been.called; + expect(history.undoAnnotation()).to.equal("annotation2"); + }); + }); + describe("#undo", function () { it("returns a difference", function () { expect(history.undo().changes()).to.eql({});