Saving graph to and reinstating from localStorage

This commit is contained in:
Ansis Brammanis
2013-02-06 12:48:42 -05:00
parent a4bf7c689f
commit a21da4f15f
5 changed files with 100 additions and 12 deletions

View File

@@ -227,10 +227,53 @@ iD.Graph.prototype = {
var items = [];
for (var i in this.entities) {
var entity = this.entities[i];
if (entity && entity.intersects(extent, this)) {
if (entity && this.hasAllChildren(entity) && entity.intersects(extent, this)) {
items.push(entity);
}
}
return items;
},
hasAllChildren: function(entity) {
// we're only checking changed entities, since we assume fetched data
// must have all children present
if (this.entities.hasOwnProperty(entity.id)) {
if (entity.type === 'way') {
for (i = 0; i < entity.nodes.length; i++) {
if (!this.entities[entity.nodes[i]]) return false;
}
} else if (entity.type === 'relation') {
for (i = 0; i < entity.members.length; i++) {
if (!this.entities[entity.members[i].id]) return false;
}
}
}
return true;
},
// Obliterates any existing entities
load: function(entities) {
var base = this.base(),
i, entity, prefix;
this.entities = Object.create(base.entities);
for (i in entities) {
entity = entities[i];
prefix = i[0];
if (prefix == 'n') {
this.entities[i] = new iD.Node(entity);
} else if (prefix == 'w') {
this.entities[i] = new iD.Way(entity);
} else if (prefix == 'r') {
this.entities[i] = new iD.Relation(entity);
}
this._updateCalculated(base.entities[i], this.entities[i]);
}
return this;
}
};

View File

@@ -1,4 +1,4 @@
iD.History = function() {
iD.History = function(context) {
var stack, index,
imagery_used = 'Bing',
dispatch = d3.dispatch('change', 'undone', 'redone');
@@ -26,6 +26,10 @@ iD.History = function() {
return difference;
}
function getKey(n) {
return 'iD_' + window.location.origin + '_' + n;
}
var history = {
graph: function() {
return stack[index].graph;
@@ -148,8 +152,47 @@ iD.History = function() {
reset: function() {
stack = [{graph: iD.Graph()}];
index = 0;
this.load();
dispatch.change();
},
save: function() {
var json = JSON.stringify(stack.map(function(i) {
return _.extend(i, {
graph: i.graph.entities
});
}));
context.storage(getKey('history'), json);
context.storage(getKey('nextIDs'), JSON.stringify(iD.Entity.id.next));
context.storage(getKey('index'), index);
context.storage(getKey('lock'), '');
},
lock: function() {
if (context.storage(getKey('lock'))) return false;
context.storage(getKey('lock'), true);
return true;
},
load: function() {
if (!this.lock()) return;
var json = context.storage(getKey('history')),
nextIDs = context.storage(getKey('nextIDs')),
index_ = context.storage(getKey('index'));
if (!json) return;
if (nextIDs) iD.Entity.id.next = JSON.parse(nextIDs);
if (index_ !== null) index = parseInt(index_, 10);
stack = JSON.parse(json).map(function(d) {
d.graph = iD.Graph().load(d.graph);
return d;
});
}
};
history.reset();

View File

@@ -1,18 +1,19 @@
window.iD = function () {
var context = {},
history = iD.History(),
storage = localStorage || {},
dispatch = d3.dispatch('enter', 'exit'),
mode,
container,
ui = iD.ui(context),
map = iD.Map(context);
storage = localStorage || {};
context.storage = function(k, v) {
if (arguments.length === 1) return storage[k];
else storage[k] = v;
};
var history = iD.History(context),
dispatch = d3.dispatch('enter', 'exit'),
mode,
container,
ui = iD.ui(context),
map = iD.Map(context);
// the connection requires .storage() to be available on calling.
var connection = iD.Connection(context);

View File

@@ -194,6 +194,7 @@ iD.ui = function(context) {
history.on('change.editor', function() {
window.onbeforeunload = history.hasChanges() ? function() {
history.save();
return 'You have unsaved changes.';
} : null;
@@ -252,7 +253,7 @@ iD.ui = function(context) {
context.enter(iD.modes.Browse(context));
if (!context.storage('sawSplash')) {
iD.ui.splash();
iD.ui.splash(context.container());
context.storage('sawSplash', true);
}
};

View File

@@ -1,5 +1,5 @@
iD.ui.splash = function() {
var modal = iD.ui.modal();
iD.ui.splash = function(selection) {
var modal = iD.ui.modal(selection);
modal.select('.modal')
.attr('class', 'modal-splash modal');