mirror of
https://github.com/FoggedLens/iD.git
synced 2026-05-20 23:44:47 +02:00
Convert History to module pattern
There is only ever one History, so memory use is not a concern.
This commit is contained in:
+75
-77
@@ -1,85 +1,83 @@
|
||||
iD.History = function() {
|
||||
if (!(this instanceof iD.History)) return new iD.History();
|
||||
this.stack = [iD.Graph()];
|
||||
this.index = 0;
|
||||
};
|
||||
var stack = [iD.Graph()],
|
||||
index = 0;
|
||||
|
||||
iD.History.prototype = {
|
||||
return {
|
||||
graph: function () {
|
||||
return stack[index];
|
||||
},
|
||||
|
||||
graph: function() {
|
||||
return this.stack[this.index];
|
||||
},
|
||||
merge: function (graph) {
|
||||
for (var i = 0; i < stack.length; i++) {
|
||||
stack[i] = stack[i].merge(graph);
|
||||
}
|
||||
},
|
||||
|
||||
merge: function(graph) {
|
||||
for (var i = 0; i < this.stack.length; i++) {
|
||||
this.stack[i] = this.stack[i].merge(graph);
|
||||
}
|
||||
},
|
||||
|
||||
perform: function(action) {
|
||||
this.stack = this.stack.slice(0, this.index + 1);
|
||||
this.stack.push(action(this.graph()));
|
||||
this.index++;
|
||||
},
|
||||
|
||||
replace: function(action) {
|
||||
// assert(this.index == this.stack.length - 1)
|
||||
this.stack[this.index] = action(this.graph());
|
||||
},
|
||||
|
||||
undo: function() {
|
||||
while (this.index > 0) {
|
||||
this.index--;
|
||||
if (this.stack[this.index].annotation) break;
|
||||
}
|
||||
},
|
||||
|
||||
redo: function() {
|
||||
while (this.index < this.stack.length - 1) {
|
||||
this.index++;
|
||||
if (this.stack[this.index].annotation) break;
|
||||
}
|
||||
},
|
||||
|
||||
undoAnnotation: function() {
|
||||
var index = this.index;
|
||||
while (index >= 0) {
|
||||
if (this.stack[index].annotation) return this.stack[index].annotation;
|
||||
index--;
|
||||
}
|
||||
},
|
||||
|
||||
redoAnnotation: function() {
|
||||
var index = this.index + 1;
|
||||
while (index <= this.stack.length - 1) {
|
||||
if (this.stack[index].annotation) return this.stack[index].annotation;
|
||||
perform: function (action) {
|
||||
stack = stack.slice(0, index + 1);
|
||||
stack.push(action(this.graph()));
|
||||
index++;
|
||||
},
|
||||
|
||||
replace: function (action) {
|
||||
// assert(index == stack.length - 1)
|
||||
stack[index] = action(this.graph());
|
||||
},
|
||||
|
||||
undo: function () {
|
||||
while (index > 0) {
|
||||
index--;
|
||||
if (stack[index].annotation) break;
|
||||
}
|
||||
},
|
||||
|
||||
redo: function () {
|
||||
while (index < stack.length - 1) {
|
||||
index++;
|
||||
if (stack[index].annotation) break;
|
||||
}
|
||||
},
|
||||
|
||||
undoAnnotation: function () {
|
||||
var i = index;
|
||||
while (i >= 0) {
|
||||
if (stack[i].annotation) return stack[i].annotation;
|
||||
i--;
|
||||
}
|
||||
},
|
||||
|
||||
redoAnnotation: function () {
|
||||
var i = index + 1;
|
||||
while (i <= stack.length - 1) {
|
||||
if (stack[i].annotation) return stack[i].annotation;
|
||||
i++;
|
||||
}
|
||||
},
|
||||
|
||||
// generate reports of changes for changesets to use
|
||||
modify: function () {
|
||||
return stack[index].modifications();
|
||||
},
|
||||
|
||||
create: function () {
|
||||
return stack[index].creations();
|
||||
},
|
||||
|
||||
'delete': function () {
|
||||
return _.difference(
|
||||
_.pluck(stack[0].entities, 'id'),
|
||||
_.pluck(stack[index].entities, 'id')
|
||||
).map(function (id) {
|
||||
return stack[0].fetch(id);
|
||||
});
|
||||
},
|
||||
|
||||
changes: function () {
|
||||
return {
|
||||
modify: this.modify(),
|
||||
create: this.create(),
|
||||
'delete': this['delete']()
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
// generate reports of changes for changesets to use
|
||||
modify: function() {
|
||||
return this.stack[this.index].modifications();
|
||||
},
|
||||
|
||||
create: function() {
|
||||
return this.stack[this.index].creations();
|
||||
},
|
||||
|
||||
'delete': function() {
|
||||
return _.difference(
|
||||
_.pluck(this.stack[0].entities, 'id'),
|
||||
_.pluck(this.stack[this.index].entities, 'id')
|
||||
).map(function(id) {
|
||||
return this.stack[0].fetch(id);
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
changes: function() {
|
||||
return {
|
||||
modify: this.modify(),
|
||||
create: this.create(),
|
||||
'delete': this['delete']()
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
@@ -72,6 +72,7 @@
|
||||
<script src="spec/oauth.js"></script>
|
||||
<script src="spec/graph.js"></script>
|
||||
<script src="spec/entity.js"></script>
|
||||
<script src="spec/history.js"></script>
|
||||
<script src="spec/connection.js"></script>
|
||||
<script src="spec/geojson.js"></script>
|
||||
<script src="spec/xml.js"></script>
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
describe("History", function () {
|
||||
var history, spy,
|
||||
graph = iD.Graph([], "action"),
|
||||
action = function() { return graph; };
|
||||
|
||||
beforeEach(function () {
|
||||
history = iD.History();
|
||||
});
|
||||
|
||||
describe("#graph", function () {
|
||||
it("returns the current graph", function () {
|
||||
expect(history.graph()).to.be.an.instanceOf(iD.Graph);
|
||||
});
|
||||
});
|
||||
|
||||
describe("#perform", function () {
|
||||
it("updates the graph", function () {
|
||||
history.perform(action);
|
||||
expect(history.graph()).to.equal(graph);
|
||||
});
|
||||
|
||||
it("pushes the undo stack", function () {
|
||||
history.perform(action);
|
||||
expect(history.undoAnnotation()).to.equal("action");
|
||||
});
|
||||
});
|
||||
|
||||
describe("#undo", function () {
|
||||
it("pops the undo stack", function () {
|
||||
history.perform(action);
|
||||
history.undo();
|
||||
expect(history.undoAnnotation()).to.be.undefined;
|
||||
});
|
||||
|
||||
it("pushes the redo stack", function () {
|
||||
history.perform(action);
|
||||
history.undo();
|
||||
expect(history.redoAnnotation()).to.equal("action");
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user