mirror of
https://github.com/FoggedLens/iD.git
synced 2026-05-16 22:03:37 +02:00
Add iD.Context
This is a facade interface that ties together a bunch of different internal objects and will make it easier to write tests for behaviors, modes, and operations.
This commit is contained in:
@@ -27,6 +27,7 @@ all: \
|
||||
js/lib/sha.js \
|
||||
js/id/start.js \
|
||||
js/id/id.js \
|
||||
js/id/context.js \
|
||||
js/id/connection.js \
|
||||
js/id/oauth.js \
|
||||
js/id/services/*.js \
|
||||
|
||||
+2
-1
@@ -122,9 +122,10 @@
|
||||
<script src='js/id/graph/relation.js'></script>
|
||||
<script src='js/id/graph/way.js'></script>
|
||||
|
||||
<script src='js/id/connection.js'></script>
|
||||
<script src='js/id/context.js'></script>
|
||||
<script src='js/id/controller.js'></script>
|
||||
<script src='js/id/validate.js'></script>
|
||||
<script src='js/id/connection.js'></script>
|
||||
|
||||
<script src='locale/locale.js'></script>
|
||||
<script src='locale/en.js'></script>
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
iD.behavior.AddWay = function(mode) {
|
||||
var map = mode.map,
|
||||
controller = mode.controller,
|
||||
event = d3.dispatch('start', 'startFromWay', 'startFromNode', 'startFromMidpoint'),
|
||||
draw = iD.behavior.Draw(map);
|
||||
iD.behavior.AddWay = function(context) {
|
||||
var event = d3.dispatch('start', 'startFromWay', 'startFromNode', 'startFromMidpoint'),
|
||||
draw = iD.behavior.Draw(context);
|
||||
|
||||
var addWay = function(surface) {
|
||||
draw.on('click', event.start)
|
||||
@@ -12,7 +10,8 @@ iD.behavior.AddWay = function(mode) {
|
||||
.on('cancel', addWay.cancel)
|
||||
.on('finish', addWay.cancel);
|
||||
|
||||
map.fastEnable(false)
|
||||
context.map()
|
||||
.fastEnable(false)
|
||||
.minzoom(16)
|
||||
.dblclickEnable(false);
|
||||
|
||||
@@ -20,19 +19,20 @@ iD.behavior.AddWay = function(mode) {
|
||||
};
|
||||
|
||||
addWay.off = function(surface) {
|
||||
map.fastEnable(true)
|
||||
context.map()
|
||||
.fastEnable(true)
|
||||
.minzoom(0)
|
||||
.tail(false);
|
||||
|
||||
window.setTimeout(function() {
|
||||
map.dblclickEnable(true);
|
||||
context.map().dblclickEnable(true);
|
||||
}, 1000);
|
||||
|
||||
surface.call(draw.off);
|
||||
};
|
||||
|
||||
addWay.cancel = function() {
|
||||
controller.enter(iD.modes.Browse());
|
||||
context.enter(iD.modes.Browse(context));
|
||||
};
|
||||
|
||||
return d3.rebind(addWay, event, 'on');
|
||||
|
||||
@@ -1,16 +1,13 @@
|
||||
iD.behavior.DragMidpoint = function(mode) {
|
||||
var history = mode.history,
|
||||
projection = mode.map.projection;
|
||||
|
||||
iD.behavior.DragMidpoint = function(context) {
|
||||
var behavior = iD.behavior.drag()
|
||||
.delegate(".midpoint")
|
||||
.origin(function(d) {
|
||||
return projection(d.loc);
|
||||
return context.projection(d.loc);
|
||||
})
|
||||
.on('start', function(d) {
|
||||
var node = iD.Node();
|
||||
|
||||
history.perform(iD.actions.AddMidpoint(d, node));
|
||||
context.perform(iD.actions.AddMidpoint(d, node));
|
||||
|
||||
var vertex = d3.selectAll('.vertex')
|
||||
.filter(function(data) { return data.id === node.id; });
|
||||
@@ -19,11 +16,11 @@ iD.behavior.DragMidpoint = function(mode) {
|
||||
})
|
||||
.on('move', function(d) {
|
||||
d3.event.sourceEvent.stopPropagation();
|
||||
history.replace(
|
||||
iD.actions.MoveNode(d.id, projection.invert(d3.event.point)));
|
||||
context.replace(
|
||||
iD.actions.MoveNode(d.id, context.projection.invert(d3.event.point)));
|
||||
})
|
||||
.on('end', function() {
|
||||
history.replace(
|
||||
context.replace(
|
||||
iD.actions.Noop(),
|
||||
t('operations.add.annotation.vertex'));
|
||||
});
|
||||
|
||||
+10
-12
@@ -1,8 +1,6 @@
|
||||
iD.behavior.DragNode = function(mode) {
|
||||
var history = mode.history,
|
||||
size = mode.map.size(),
|
||||
nudgeInterval,
|
||||
projection = mode.map.projection;
|
||||
iD.behavior.DragNode = function(context) {
|
||||
var size = context.map().size(),
|
||||
nudgeInterval;
|
||||
|
||||
function edge(point) {
|
||||
var pad = [30, 100, 30, 100];
|
||||
@@ -16,7 +14,7 @@ iD.behavior.DragNode = function(mode) {
|
||||
function startNudge(nudge) {
|
||||
if (nudgeInterval) window.clearInterval(nudgeInterval);
|
||||
nudgeInterval = window.setInterval(function() {
|
||||
mode.map.pan(nudge).redraw();
|
||||
context.map().pan(nudge).redraw();
|
||||
}, 50);
|
||||
}
|
||||
|
||||
@@ -26,16 +24,16 @@ iD.behavior.DragNode = function(mode) {
|
||||
}
|
||||
|
||||
function annotation(entity) {
|
||||
return t('operations.move.annotation.' + entity.geometry(mode.history.graph()));
|
||||
return t('operations.move.annotation.' + entity.geometry(context.graph()));
|
||||
}
|
||||
|
||||
return iD.behavior.drag()
|
||||
.delegate(".node")
|
||||
.origin(function(entity) {
|
||||
return projection(entity.loc);
|
||||
return context.projection(entity.loc);
|
||||
})
|
||||
.on('start', function() {
|
||||
history.perform(
|
||||
context.perform(
|
||||
iD.actions.Noop());
|
||||
})
|
||||
.on('move', function(entity) {
|
||||
@@ -45,13 +43,13 @@ iD.behavior.DragNode = function(mode) {
|
||||
if (nudge) startNudge(nudge);
|
||||
else stopNudge();
|
||||
|
||||
history.replace(
|
||||
iD.actions.MoveNode(entity.id, projection.invert(d3.event.point)),
|
||||
context.replace(
|
||||
iD.actions.MoveNode(entity.id, context.projection.invert(d3.event.point)),
|
||||
annotation(entity));
|
||||
})
|
||||
.on('end', function(entity) {
|
||||
stopNudge();
|
||||
history.replace(
|
||||
context.replace(
|
||||
iD.actions.Noop(),
|
||||
annotation(entity));
|
||||
});
|
||||
|
||||
+12
-12
@@ -1,7 +1,8 @@
|
||||
iD.behavior.Draw = function(map) {
|
||||
iD.behavior.Draw = function(context) {
|
||||
var event = d3.dispatch('move', 'click', 'clickWay', 'clickNode', 'clickMidpoint', 'undo', 'cancel', 'finish'),
|
||||
keybinding = d3.keybinding('draw'),
|
||||
down, surface, hover;
|
||||
hover = iD.behavior.Hover(),
|
||||
down;
|
||||
|
||||
function datum() {
|
||||
if (d3.event.altKey) {
|
||||
@@ -28,7 +29,7 @@ iD.behavior.Draw = function(map) {
|
||||
function click() {
|
||||
var d = datum();
|
||||
if (d.type === 'way') {
|
||||
var choice = iD.geo.chooseIndex(d, d3.mouse(map.surface.node()), map);
|
||||
var choice = iD.geo.chooseIndex(d, d3.mouse(context.surface().node()), context.map());
|
||||
event.clickWay(d, choice.loc, choice.index);
|
||||
|
||||
} else if (d.type === 'node') {
|
||||
@@ -38,19 +39,19 @@ iD.behavior.Draw = function(map) {
|
||||
event.clickMidpoint(d);
|
||||
|
||||
} else {
|
||||
event.click(map.mouseCoordinates());
|
||||
event.click(context.map().mouseCoordinates());
|
||||
}
|
||||
}
|
||||
|
||||
function keydown() {
|
||||
if (d3.event.keyCode === d3.keybinding.modifierCodes.alt) {
|
||||
surface.call(hover.off);
|
||||
context.uninstall(hover);
|
||||
}
|
||||
}
|
||||
|
||||
function keyup() {
|
||||
if (d3.event.keyCode === d3.keybinding.modifierCodes.alt) {
|
||||
surface.call(hover);
|
||||
context.install(hover);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,8 +71,7 @@ iD.behavior.Draw = function(map) {
|
||||
}
|
||||
|
||||
function draw(selection) {
|
||||
surface = selection;
|
||||
hover = iD.behavior.Hover();
|
||||
context.install(hover);
|
||||
|
||||
keybinding
|
||||
.on('⌫', backspace)
|
||||
@@ -83,8 +83,7 @@ iD.behavior.Draw = function(map) {
|
||||
.on('mousedown.draw', mousedown)
|
||||
.on('mouseup.draw', mouseup)
|
||||
.on('mousemove.draw', mousemove)
|
||||
.on('click.draw', click)
|
||||
.call(hover);
|
||||
.on('click.draw', click);
|
||||
|
||||
d3.select(document)
|
||||
.call(keybinding)
|
||||
@@ -95,12 +94,13 @@ iD.behavior.Draw = function(map) {
|
||||
}
|
||||
|
||||
draw.off = function(selection) {
|
||||
context.uninstall(hover);
|
||||
|
||||
selection
|
||||
.on('mousedown.draw', null)
|
||||
.on('mouseup.draw', null)
|
||||
.on('mousemove.draw', null)
|
||||
.on('click.draw', null)
|
||||
.call(hover.off);
|
||||
.on('click.draw', null);
|
||||
|
||||
d3.select(document)
|
||||
.call(keybinding.off)
|
||||
|
||||
+35
-34
@@ -1,35 +1,32 @@
|
||||
iD.behavior.DrawWay = function(wayId, index, mode, baseGraph) {
|
||||
var map = mode.map,
|
||||
history = mode.history,
|
||||
controller = mode.controller,
|
||||
way = history.graph().entity(wayId),
|
||||
iD.behavior.DrawWay = function(context, wayId, index, mode, baseGraph) {
|
||||
var way = context.entity(wayId),
|
||||
finished = false,
|
||||
annotation = t((way.isDegenerate() ?
|
||||
'operations.start.annotation.' :
|
||||
'operations.continue.annotation.') + way.geometry(history.graph())),
|
||||
draw = iD.behavior.Draw(map);
|
||||
'operations.continue.annotation.') + context.geometry(wayId)),
|
||||
draw = iD.behavior.Draw(context);
|
||||
|
||||
var node = iD.Node({loc: map.mouseCoordinates()}),
|
||||
var node = iD.Node({loc: context.map().mouseCoordinates()}),
|
||||
nodeId = node.id;
|
||||
|
||||
history[way.isDegenerate() ? 'replace' : 'perform'](
|
||||
context[way.isDegenerate() ? 'replace' : 'perform'](
|
||||
iD.actions.AddEntity(node),
|
||||
iD.actions.AddVertex(wayId, node.id, index));
|
||||
|
||||
function move(datum) {
|
||||
var loc = map.mouseCoordinates();
|
||||
var loc = context.map().mouseCoordinates();
|
||||
|
||||
if (datum.type === 'node' || datum.type === 'midpoint') {
|
||||
loc = datum.loc;
|
||||
} else if (datum.type === 'way') {
|
||||
loc = iD.geo.chooseIndex(datum, d3.mouse(map.surface.node()), map).loc;
|
||||
loc = iD.geo.chooseIndex(datum, d3.mouse(context.surface().node()), context.map()).loc;
|
||||
}
|
||||
|
||||
history.replace(iD.actions.MoveNode(nodeId, loc));
|
||||
context.replace(iD.actions.MoveNode(nodeId, loc));
|
||||
}
|
||||
|
||||
function undone() {
|
||||
controller.enter(iD.modes.Browse());
|
||||
context.enter(iD.modes.Browse(context));
|
||||
}
|
||||
|
||||
var drawWay = function(surface) {
|
||||
@@ -38,11 +35,12 @@ iD.behavior.DrawWay = function(wayId, index, mode, baseGraph) {
|
||||
.on('clickWay', drawWay.addWay)
|
||||
.on('clickNode', drawWay.addNode)
|
||||
.on('clickMidpoint', drawWay.addMidpoint)
|
||||
.on('undo', history.undo)
|
||||
.on('undo', context.undo)
|
||||
.on('cancel', drawWay.cancel)
|
||||
.on('finish', drawWay.finish);
|
||||
|
||||
map.fastEnable(false)
|
||||
context.map()
|
||||
.fastEnable(false)
|
||||
.minzoom(16)
|
||||
.dblclickEnable(false);
|
||||
|
||||
@@ -51,26 +49,29 @@ iD.behavior.DrawWay = function(wayId, index, mode, baseGraph) {
|
||||
.filter(function (d) { return d.id === wayId || d.id === nodeId; })
|
||||
.classed('active', true);
|
||||
|
||||
history.on('undone.draw', undone);
|
||||
context.history()
|
||||
.on('undone.draw', undone);
|
||||
};
|
||||
|
||||
drawWay.off = function(surface) {
|
||||
if (!finished)
|
||||
history.pop();
|
||||
context.pop();
|
||||
|
||||
map.fastEnable(true)
|
||||
context.map()
|
||||
.fastEnable(true)
|
||||
.minzoom(0)
|
||||
.tail(false);
|
||||
|
||||
window.setTimeout(function() {
|
||||
map.dblclickEnable(true);
|
||||
context.map().dblclickEnable(true);
|
||||
}, 1000);
|
||||
|
||||
surface.call(draw.off)
|
||||
.selectAll('.way, .node')
|
||||
.classed('active', false);
|
||||
|
||||
history.on('undone.draw', null);
|
||||
context.history()
|
||||
.on('undone.draw', null);
|
||||
};
|
||||
|
||||
function ReplaceTemporaryNode(newNode) {
|
||||
@@ -85,74 +86,74 @@ iD.behavior.DrawWay = function(wayId, index, mode, baseGraph) {
|
||||
drawWay.add = function(loc) {
|
||||
var newNode = iD.Node({loc: loc});
|
||||
|
||||
history.replace(
|
||||
context.replace(
|
||||
iD.actions.AddEntity(newNode),
|
||||
ReplaceTemporaryNode(newNode),
|
||||
annotation);
|
||||
|
||||
finished = true;
|
||||
controller.enter(mode);
|
||||
context.enter(mode);
|
||||
};
|
||||
|
||||
// Connect the way to an existing way.
|
||||
drawWay.addWay = function(way, loc, wayIndex) {
|
||||
var newNode = iD.Node({loc: loc});
|
||||
|
||||
history.perform(
|
||||
context.perform(
|
||||
iD.actions.AddEntity(newNode),
|
||||
iD.actions.AddVertex(way.id, newNode.id, wayIndex),
|
||||
ReplaceTemporaryNode(newNode),
|
||||
annotation);
|
||||
|
||||
finished = true;
|
||||
controller.enter(mode);
|
||||
context.enter(mode);
|
||||
};
|
||||
|
||||
// Connect the way to an existing node and continue drawing.
|
||||
drawWay.addNode = function(node) {
|
||||
history.perform(
|
||||
context.perform(
|
||||
ReplaceTemporaryNode(node),
|
||||
annotation);
|
||||
|
||||
finished = true;
|
||||
controller.enter(mode);
|
||||
context.enter(mode);
|
||||
};
|
||||
|
||||
// Add a midpoint, connect the way to it, and continue drawing.
|
||||
drawWay.addMidpoint = function(midpoint) {
|
||||
var node = iD.Node();
|
||||
|
||||
history.perform(
|
||||
context.perform(
|
||||
iD.actions.AddMidpoint(midpoint, node),
|
||||
ReplaceTemporaryNode(node),
|
||||
annotation);
|
||||
|
||||
finished = true;
|
||||
controller.enter(mode);
|
||||
context.enter(mode);
|
||||
};
|
||||
|
||||
// Finish the draw operation, removing the temporary node. If the way has enough
|
||||
// nodes to be valid, it's selected. Otherwise, return to browse mode.
|
||||
drawWay.finish = function() {
|
||||
history.pop();
|
||||
context.pop();
|
||||
finished = true;
|
||||
|
||||
var way = history.graph().entity(wayId);
|
||||
var way = context.entity(wayId);
|
||||
if (way) {
|
||||
controller.enter(iD.modes.Select([way.id], true));
|
||||
context.enter(iD.modes.Select(context, [way.id], true));
|
||||
} else {
|
||||
controller.enter(iD.modes.Browse());
|
||||
context.enter(iD.modes.Browse(context));
|
||||
}
|
||||
};
|
||||
|
||||
// Cancel the draw operation and return to browse, deleting everything drawn.
|
||||
drawWay.cancel = function() {
|
||||
history.perform(
|
||||
context.perform(
|
||||
d3.functor(baseGraph),
|
||||
t('operations.cancel_draw.annotation'));
|
||||
|
||||
finished = true;
|
||||
controller.enter(iD.modes.Browse());
|
||||
context.enter(iD.modes.Browse(context));
|
||||
};
|
||||
|
||||
return d3.rebind(drawWay, event, 'on');
|
||||
|
||||
+15
-14
@@ -1,4 +1,4 @@
|
||||
iD.behavior.Hash = function(controller, map) {
|
||||
iD.behavior.Hash = function(context) {
|
||||
var s0 = null, // cached location.hash
|
||||
lat = 90 - 1e-8; // allowable latitude range
|
||||
|
||||
@@ -27,13 +27,13 @@ iD.behavior.Hash = function(controller, map) {
|
||||
};
|
||||
|
||||
var move = _.throttle(function() {
|
||||
var s1 = formatter(map);
|
||||
var s1 = formatter(context.map());
|
||||
if (s0 !== s1) location.replace(s0 = s1); // don't recenter the map!
|
||||
}, 100);
|
||||
|
||||
function hashchange() {
|
||||
if (location.hash === s0) return; // ignore spurious hashchange events
|
||||
if (parser(map, (s0 = location.hash).substring(1))) {
|
||||
if (parser(context.map(), (s0 = location.hash).substring(1))) {
|
||||
move(); // replace bogus hash
|
||||
}
|
||||
}
|
||||
@@ -42,24 +42,24 @@ iD.behavior.Hash = function(controller, map) {
|
||||
// do so before any features are loaded. thus wait for the feature to
|
||||
// be loaded and then select
|
||||
function willselect(id) {
|
||||
map.on('drawn.hash', function() {
|
||||
var entity = map.history().graph().entity(id);
|
||||
if (entity === undefined) return;
|
||||
else selectoff();
|
||||
controller.enter(iD.modes.Select([entity.id]));
|
||||
map.on('drawn.hash', null);
|
||||
context.map().on('drawn.hash', function() {
|
||||
if (!context.entity(id)) return;
|
||||
selectoff();
|
||||
context.enter(iD.modes.Select([id]));
|
||||
});
|
||||
controller.on('enter.hash', function() {
|
||||
if (controller.mode.id !== 'browse') selectoff();
|
||||
|
||||
context.controller().on('enter.hash', function() {
|
||||
if (context.mode().id !== 'browse') selectoff();
|
||||
});
|
||||
}
|
||||
|
||||
function selectoff() {
|
||||
map.on('drawn.hash', null);
|
||||
context.map().on('drawn.hash', null);
|
||||
}
|
||||
|
||||
function hash() {
|
||||
map.on('move.hash', move);
|
||||
context.map()
|
||||
.on('move.hash', move);
|
||||
|
||||
d3.select(window)
|
||||
.on('hashchange.hash', hashchange);
|
||||
@@ -75,7 +75,8 @@ iD.behavior.Hash = function(controller, map) {
|
||||
}
|
||||
|
||||
hash.off = function() {
|
||||
map.on('move.hash', null);
|
||||
context.map()
|
||||
.on('move.hash', null);
|
||||
|
||||
d3.select(window)
|
||||
.on('hashchange.hash', null);
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
iD.behavior.Select = function(mode) {
|
||||
var controller = mode.controller;
|
||||
|
||||
iD.behavior.Select = function(context) {
|
||||
function click() {
|
||||
var datum = d3.select(d3.event.target).datum();
|
||||
if (datum instanceof iD.Entity) {
|
||||
controller.enter(iD.modes.Select([datum.id]));
|
||||
context.enter(iD.modes.Select(context, [datum.id]));
|
||||
} else {
|
||||
controller.enter(iD.modes.Browse());
|
||||
context.enter(iD.modes.Browse(context));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
iD.Context = function() {
|
||||
var history = iD.History(),
|
||||
connection = iD.Connection(),
|
||||
controller = iD.Controller(),
|
||||
container,
|
||||
map = iD.Map().connection(connection).history(history);
|
||||
|
||||
var context = {};
|
||||
|
||||
context.container = function (_) {
|
||||
if (!arguments.length) return container;
|
||||
container = _;
|
||||
return context;
|
||||
};
|
||||
|
||||
context.connection = function () { return connection; };
|
||||
|
||||
context.history = function () { return history; };
|
||||
context.graph = history.graph;
|
||||
context.perform = history.perform;
|
||||
context.replace = history.replace;
|
||||
context.pop = history.pop;
|
||||
context.undo = history.undo;
|
||||
context.redo = history.undo;
|
||||
context.changes = history.changes;
|
||||
|
||||
context.entity = function (id) { return history.graph().entity(id); };
|
||||
context.geometry = function (id) { return context.entity(id).geometry(history.graph()); };
|
||||
|
||||
context.controller = function () { return controller; };
|
||||
context.enter = controller.enter;
|
||||
context.mode = function () { return controller.mode; };
|
||||
|
||||
context.install = function (behavior) { context.surface().call(behavior); };
|
||||
context.uninstall = function (behavior) { context.surface().call(behavior.off); };
|
||||
|
||||
context.map = function () { return map; };
|
||||
context.background = function () { return map.background; };
|
||||
context.surface = function () { return map.surface; };
|
||||
context.projection = map.projection;
|
||||
context.tail = map.tail;
|
||||
|
||||
return context;
|
||||
};
|
||||
+1
-5
@@ -1,14 +1,10 @@
|
||||
// A controller holds a single action at a time and calls `.enter` and `.exit`
|
||||
// to bind and unbind actions.
|
||||
iD.Controller = function(map, history) {
|
||||
iD.Controller = function() {
|
||||
var event = d3.dispatch('enter', 'exit');
|
||||
var controller = { mode: null };
|
||||
|
||||
controller.enter = function(mode) {
|
||||
mode.controller = controller;
|
||||
mode.history = history;
|
||||
mode.map = map;
|
||||
|
||||
if (controller.mode) {
|
||||
controller.mode.exit();
|
||||
event.exit(controller.mode);
|
||||
|
||||
+25
-14
@@ -2,17 +2,22 @@ window.iD = function(container) {
|
||||
// the reported, displayed version of iD.
|
||||
var version = '0.0.0-alpha1';
|
||||
|
||||
var connection = iD.Connection()
|
||||
.version(version),
|
||||
history = iD.History(),
|
||||
map = iD.Map()
|
||||
.connection(connection)
|
||||
.history(history),
|
||||
controller = iD.Controller(map, history);
|
||||
var context = iD.Context();
|
||||
|
||||
map.background.source(iD.BackgroundSource.Bing);
|
||||
var connection = context.connection(),
|
||||
history = context.history(),
|
||||
map = context.map(),
|
||||
controller = context.controller();
|
||||
|
||||
context.connection()
|
||||
.version(version);
|
||||
|
||||
context.background()
|
||||
.source(iD.BackgroundSource.Bing);
|
||||
|
||||
function editor(container) {
|
||||
context.container(container);
|
||||
|
||||
if (!iD.supported()) {
|
||||
container.html('This editor is supported in Firefox, Chrome, Safari, Opera, ' +
|
||||
'and Internet Explorer 9 and above. Please upgrade your browser ' +
|
||||
@@ -39,8 +44,14 @@ window.iD = function(container) {
|
||||
var buttons_joined = limiter.append('div')
|
||||
.attr('class', 'button-wrap joined col4');
|
||||
|
||||
var modes = [
|
||||
iD.modes.Browse(context),
|
||||
iD.modes.AddPoint(context),
|
||||
iD.modes.AddLine(context),
|
||||
iD.modes.AddArea(context)];
|
||||
|
||||
var buttons = buttons_joined.selectAll('button.add-button')
|
||||
.data([iD.modes.Browse(), iD.modes.AddPoint(), iD.modes.AddLine(), iD.modes.AddArea()])
|
||||
.data(modes)
|
||||
.enter().append('button')
|
||||
.attr('tabindex', -1)
|
||||
.attr('class', function (mode) { return mode.title + ' add-button col3'; })
|
||||
@@ -57,7 +68,7 @@ window.iD = function(container) {
|
||||
} else {
|
||||
buttons.attr('disabled', 'disabled');
|
||||
notice.message(true);
|
||||
controller.enter(iD.modes.Browse());
|
||||
controller.enter(iD.modes.Browse(context));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,7 +117,7 @@ window.iD = function(container) {
|
||||
|
||||
var save_button = limiter.append('div').attr('class','button-wrap col1').append('button')
|
||||
.attr('class', 'save col12')
|
||||
.call(iD.ui.save().map(map).controller(controller));
|
||||
.call(iD.ui.save(context));
|
||||
|
||||
var zoom = container.append('div')
|
||||
.attr('class', 'zoombuttons map-control')
|
||||
@@ -227,14 +238,14 @@ window.iD = function(container) {
|
||||
.on('⌃+⇧+Z', function() { history.redo(); })
|
||||
.on('⌫', function() { d3.event.preventDefault(); });
|
||||
|
||||
[iD.modes.Browse(), iD.modes.AddPoint(), iD.modes.AddLine(), iD.modes.AddArea()].forEach(function(m) {
|
||||
modes.forEach(function(m) {
|
||||
keybinding.on(m.key, function() { if (map.editable()) controller.enter(m); });
|
||||
});
|
||||
|
||||
d3.select(document)
|
||||
.call(keybinding);
|
||||
|
||||
var hash = iD.behavior.Hash(controller, map);
|
||||
var hash = iD.behavior.Hash(context);
|
||||
|
||||
hash();
|
||||
|
||||
@@ -246,7 +257,7 @@ window.iD = function(container) {
|
||||
.on('logout.editor', connection.logout)
|
||||
.on('login.editor', connection.authenticate));
|
||||
|
||||
controller.enter(iD.modes.Browse());
|
||||
controller.enter(iD.modes.Browse(context));
|
||||
|
||||
if (!localStorage.sawSplash) {
|
||||
iD.ui.splash();
|
||||
|
||||
+17
-21
@@ -1,4 +1,4 @@
|
||||
iD.modes.AddArea = function() {
|
||||
iD.modes.AddArea = function(context) {
|
||||
var mode = {
|
||||
id: 'add-area',
|
||||
button: 'area',
|
||||
@@ -11,77 +11,73 @@ iD.modes.AddArea = function() {
|
||||
defaultTags = {area: 'yes'};
|
||||
|
||||
mode.enter = function() {
|
||||
var map = mode.map,
|
||||
history = mode.history,
|
||||
controller = mode.controller;
|
||||
|
||||
function start(loc) {
|
||||
var graph = history.graph(),
|
||||
var graph = context.graph(),
|
||||
node = iD.Node({loc: loc}),
|
||||
way = iD.Way({tags: defaultTags});
|
||||
|
||||
history.perform(
|
||||
context.perform(
|
||||
iD.actions.AddEntity(node),
|
||||
iD.actions.AddEntity(way),
|
||||
iD.actions.AddVertex(way.id, node.id),
|
||||
iD.actions.AddVertex(way.id, node.id));
|
||||
|
||||
controller.enter(iD.modes.DrawArea(way.id, graph));
|
||||
context.enter(iD.modes.DrawArea(context, way.id, graph));
|
||||
}
|
||||
|
||||
function startFromWay(other, loc, index) {
|
||||
var graph = history.graph(),
|
||||
var graph = context.graph(),
|
||||
node = iD.Node({loc: loc}),
|
||||
way = iD.Way({tags: defaultTags});
|
||||
|
||||
history.perform(
|
||||
context.perform(
|
||||
iD.actions.AddEntity(node),
|
||||
iD.actions.AddEntity(way),
|
||||
iD.actions.AddVertex(way.id, node.id),
|
||||
iD.actions.AddVertex(way.id, node.id),
|
||||
iD.actions.AddVertex(other.id, node.id, index));
|
||||
|
||||
controller.enter(iD.modes.DrawArea(way.id, graph));
|
||||
context.enter(iD.modes.DrawArea(context, way.id, graph));
|
||||
}
|
||||
|
||||
function startFromNode(node) {
|
||||
var graph = history.graph(),
|
||||
var graph = context.graph(),
|
||||
way = iD.Way({tags: defaultTags});
|
||||
|
||||
history.perform(
|
||||
context.perform(
|
||||
iD.actions.AddEntity(way),
|
||||
iD.actions.AddVertex(way.id, node.id),
|
||||
iD.actions.AddVertex(way.id, node.id));
|
||||
|
||||
controller.enter(iD.modes.DrawArea(way.id, graph));
|
||||
context.enter(iD.modes.DrawArea(context, way.id, graph));
|
||||
}
|
||||
|
||||
function startFromMidpoint(midpoint) {
|
||||
var graph = history.graph(),
|
||||
var graph = context.graph(),
|
||||
node = iD.Node(),
|
||||
way = iD.Way({tags: defaultTags});
|
||||
|
||||
history.perform(
|
||||
context.perform(
|
||||
iD.actions.AddMidpoint(midpoint, node),
|
||||
iD.actions.AddEntity(way),
|
||||
iD.actions.AddVertex(way.id, node.id),
|
||||
iD.actions.AddVertex(way.id, node.id));
|
||||
|
||||
controller.enter(iD.modes.DrawArea(way.id, graph));
|
||||
context.enter(iD.modes.DrawArea(context, way.id, graph));
|
||||
}
|
||||
|
||||
behavior = iD.behavior.AddWay(mode)
|
||||
behavior = iD.behavior.AddWay(context)
|
||||
.on('start', start)
|
||||
.on('startFromWay', startFromWay)
|
||||
.on('startFromNode', startFromNode)
|
||||
.on('startFromMidpoint', startFromMidpoint);
|
||||
|
||||
mode.map.surface.call(behavior);
|
||||
mode.map.tail(t('modes.add_area.tail'));
|
||||
context.install(behavior);
|
||||
context.tail(t('modes.add_area.tail'));
|
||||
};
|
||||
|
||||
mode.exit = function() {
|
||||
mode.map.surface.call(behavior.off);
|
||||
context.uninstall(behavior);
|
||||
};
|
||||
|
||||
return mode;
|
||||
|
||||
+19
-23
@@ -1,4 +1,4 @@
|
||||
iD.modes.AddLine = function() {
|
||||
iD.modes.AddLine = function(context) {
|
||||
var mode = {
|
||||
id: 'add-line',
|
||||
button: 'line',
|
||||
@@ -11,84 +11,80 @@ iD.modes.AddLine = function() {
|
||||
defaultTags = {highway: 'residential'};
|
||||
|
||||
mode.enter = function() {
|
||||
var map = mode.map,
|
||||
history = mode.history,
|
||||
controller = mode.controller;
|
||||
|
||||
function start(loc) {
|
||||
var graph = history.graph(),
|
||||
var graph = context.graph(),
|
||||
node = iD.Node({loc: loc}),
|
||||
way = iD.Way({tags: defaultTags});
|
||||
|
||||
history.perform(
|
||||
context.perform(
|
||||
iD.actions.AddEntity(node),
|
||||
iD.actions.AddEntity(way),
|
||||
iD.actions.AddVertex(way.id, node.id));
|
||||
|
||||
controller.enter(iD.modes.DrawLine(way.id, 'forward', graph));
|
||||
context.enter(iD.modes.DrawLine(context, way.id, 'forward', graph));
|
||||
}
|
||||
|
||||
function startFromWay(other, loc, index) {
|
||||
var graph = history.graph(),
|
||||
var graph = context.graph(),
|
||||
node = iD.Node({loc: loc}),
|
||||
way = iD.Way({tags: defaultTags});
|
||||
|
||||
history.perform(
|
||||
context.perform(
|
||||
iD.actions.AddEntity(node),
|
||||
iD.actions.AddEntity(way),
|
||||
iD.actions.AddVertex(way.id, node.id),
|
||||
iD.actions.AddVertex(other.id, node.id, index));
|
||||
|
||||
controller.enter(iD.modes.DrawLine(way.id, 'forward', graph));
|
||||
context.enter(iD.modes.DrawLine(context, way.id, 'forward', graph));
|
||||
}
|
||||
|
||||
function startFromNode(node) {
|
||||
var graph = history.graph(),
|
||||
var graph = context.graph(),
|
||||
parent = graph.parentWays(node)[0],
|
||||
isLine = parent && parent.geometry(graph) === 'line';
|
||||
|
||||
if (isLine && parent.first() === node.id) {
|
||||
controller.enter(iD.modes.DrawLine(parent.id, 'backward', graph));
|
||||
context.enter(iD.modes.DrawLine(context, parent.id, 'backward', graph));
|
||||
|
||||
} else if (isLine && parent.last() === node.id) {
|
||||
controller.enter(iD.modes.DrawLine(parent.id, 'forward', graph));
|
||||
context.enter(iD.modes.DrawLine(context, parent.id, 'forward', graph));
|
||||
|
||||
} else {
|
||||
var way = iD.Way({tags: defaultTags});
|
||||
|
||||
history.perform(
|
||||
context.perform(
|
||||
iD.actions.AddEntity(way),
|
||||
iD.actions.AddVertex(way.id, node.id));
|
||||
|
||||
controller.enter(iD.modes.DrawLine(way.id, 'forward', graph));
|
||||
context.enter(iD.modes.DrawLine(context, way.id, 'forward', graph));
|
||||
}
|
||||
}
|
||||
|
||||
function startFromMidpoint(midpoint) {
|
||||
var graph = history.graph(),
|
||||
var graph = context.graph(),
|
||||
node = iD.Node(),
|
||||
way = iD.Way({tags: defaultTags});
|
||||
|
||||
history.perform(
|
||||
context.perform(
|
||||
iD.actions.AddMidpoint(midpoint, node),
|
||||
iD.actions.AddEntity(way),
|
||||
iD.actions.AddVertex(way.id, node.id));
|
||||
|
||||
controller.enter(iD.modes.DrawLine(way.id, 'forward', graph));
|
||||
context.enter(iD.modes.DrawLine(context, way.id, 'forward', graph));
|
||||
}
|
||||
|
||||
behavior = iD.behavior.AddWay(mode)
|
||||
behavior = iD.behavior.AddWay(context)
|
||||
.on('start', start)
|
||||
.on('startFromWay', startFromWay)
|
||||
.on('startFromNode', startFromNode)
|
||||
.on('startFromMidpoint', startFromMidpoint);
|
||||
|
||||
mode.map.surface.call(behavior);
|
||||
mode.map.tail(t('modes.add_line.tail'));
|
||||
context.install(behavior);
|
||||
context.tail(t('modes.add_line.tail'));
|
||||
};
|
||||
|
||||
mode.exit = function() {
|
||||
mode.map.surface.call(behavior.off);
|
||||
context.uninstall(behavior);
|
||||
};
|
||||
|
||||
return mode;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
iD.modes.AddPoint = function() {
|
||||
iD.modes.AddPoint = function(context) {
|
||||
var mode = {
|
||||
id: 'add-point',
|
||||
title: t('modes.add_point.title'),
|
||||
@@ -9,18 +9,14 @@ iD.modes.AddPoint = function() {
|
||||
var behavior;
|
||||
|
||||
mode.enter = function() {
|
||||
var map = mode.map,
|
||||
history = mode.history,
|
||||
controller = mode.controller;
|
||||
|
||||
function add(loc) {
|
||||
var node = iD.Node({loc: loc});
|
||||
|
||||
history.perform(
|
||||
context.perform(
|
||||
iD.actions.AddEntity(node),
|
||||
t('operations.add.annotation.point'));
|
||||
|
||||
controller.enter(iD.modes.Select([node.id], true));
|
||||
context.enter(iD.modes.Select(context, [node.id], true));
|
||||
}
|
||||
|
||||
function addWay(way, loc, index) {
|
||||
@@ -32,10 +28,10 @@ iD.modes.AddPoint = function() {
|
||||
}
|
||||
|
||||
function cancel() {
|
||||
controller.enter(iD.modes.Browse());
|
||||
context.enter(iD.modes.Browse(context));
|
||||
}
|
||||
|
||||
behavior = iD.behavior.Draw(map)
|
||||
behavior = iD.behavior.Draw(context)
|
||||
.on('click', add)
|
||||
.on('clickWay', addWay)
|
||||
.on('clickNode', addNode)
|
||||
@@ -43,16 +39,13 @@ iD.modes.AddPoint = function() {
|
||||
.on('cancel', cancel)
|
||||
.on('finish', cancel);
|
||||
|
||||
mode.map.surface.call(behavior);
|
||||
mode.map.tail(t('modes.add_point.tail'));
|
||||
context.install(behavior);
|
||||
context.tail(t('modes.add_point.tail'));
|
||||
};
|
||||
|
||||
mode.exit = function() {
|
||||
var map = mode.map,
|
||||
surface = map.surface;
|
||||
|
||||
map.tail(false);
|
||||
behavior.off(surface);
|
||||
context.tail(false);
|
||||
context.uninstall(behavior);
|
||||
};
|
||||
|
||||
return mode;
|
||||
|
||||
+8
-14
@@ -1,4 +1,4 @@
|
||||
iD.modes.Browse = function() {
|
||||
iD.modes.Browse = function(context) {
|
||||
var mode = {
|
||||
button: 'browse',
|
||||
id: 'browse',
|
||||
@@ -7,27 +7,21 @@ iD.modes.Browse = function() {
|
||||
key: t('modes.browse.key')
|
||||
};
|
||||
|
||||
var behaviors;
|
||||
var behaviors = [
|
||||
iD.behavior.Hover(),
|
||||
iD.behavior.Select(context),
|
||||
iD.behavior.DragNode(context),
|
||||
iD.behavior.DragMidpoint(context)];
|
||||
|
||||
mode.enter = function() {
|
||||
var surface = mode.map.surface;
|
||||
|
||||
behaviors = [
|
||||
iD.behavior.Hover(),
|
||||
iD.behavior.Select(mode),
|
||||
iD.behavior.DragNode(mode),
|
||||
iD.behavior.DragMidpoint(mode)];
|
||||
|
||||
behaviors.forEach(function(behavior) {
|
||||
behavior(surface);
|
||||
context.install(behavior);
|
||||
});
|
||||
};
|
||||
|
||||
mode.exit = function() {
|
||||
var surface = mode.map.surface;
|
||||
|
||||
behaviors.forEach(function(behavior) {
|
||||
behavior.off(surface);
|
||||
context.uninstall(behavior);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
iD.modes.DrawArea = function(wayId, baseGraph) {
|
||||
iD.modes.DrawArea = function(context, wayId, baseGraph) {
|
||||
var mode = {
|
||||
button: 'area',
|
||||
id: 'draw-area'
|
||||
@@ -7,11 +7,11 @@ iD.modes.DrawArea = function(wayId, baseGraph) {
|
||||
var behavior;
|
||||
|
||||
mode.enter = function() {
|
||||
var way = mode.history.graph().entity(wayId),
|
||||
var way = context.entity(wayId),
|
||||
headId = way.nodes[way.nodes.length - 2],
|
||||
tailId = way.first();
|
||||
|
||||
behavior = iD.behavior.DrawWay(wayId, -1, mode, baseGraph);
|
||||
behavior = iD.behavior.DrawWay(context, wayId, -1, mode, baseGraph);
|
||||
|
||||
var addNode = behavior.addNode;
|
||||
|
||||
@@ -23,12 +23,12 @@ iD.modes.DrawArea = function(wayId, baseGraph) {
|
||||
}
|
||||
};
|
||||
|
||||
mode.map.surface.call(behavior);
|
||||
mode.map.tail(t('modes.draw_area.tail'));
|
||||
context.install(behavior);
|
||||
context.tail(t('modes.draw_area.tail'));
|
||||
};
|
||||
|
||||
mode.exit = function() {
|
||||
mode.map.surface.call(behavior.off);
|
||||
context.uninstall(behavior);
|
||||
};
|
||||
|
||||
return mode;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
iD.modes.DrawLine = function(wayId, direction, baseGraph) {
|
||||
iD.modes.DrawLine = function(context, wayId, direction, baseGraph) {
|
||||
var mode = {
|
||||
button: 'line',
|
||||
id: 'draw-line'
|
||||
@@ -7,11 +7,11 @@ iD.modes.DrawLine = function(wayId, direction, baseGraph) {
|
||||
var behavior;
|
||||
|
||||
mode.enter = function() {
|
||||
var way = mode.history.graph().entity(wayId),
|
||||
var way = context.entity(wayId),
|
||||
index = (direction === 'forward') ? undefined : 0,
|
||||
headId = (direction === 'forward') ? way.last() : way.first();
|
||||
|
||||
behavior = iD.behavior.DrawWay(wayId, index, mode, baseGraph);
|
||||
behavior = iD.behavior.DrawWay(context, wayId, index, mode, baseGraph);
|
||||
|
||||
var addNode = behavior.addNode;
|
||||
|
||||
@@ -23,12 +23,12 @@ iD.modes.DrawLine = function(wayId, direction, baseGraph) {
|
||||
}
|
||||
};
|
||||
|
||||
mode.map.surface.call(behavior);
|
||||
mode.map.tail(t('modes.draw_line.tail'));
|
||||
context.install(behavior);
|
||||
context.tail(t('modes.draw_line.tail'));
|
||||
};
|
||||
|
||||
mode.exit = function() {
|
||||
mode.map.surface.call(behavior.off);
|
||||
context.uninstall(behavior);
|
||||
};
|
||||
|
||||
return mode;
|
||||
|
||||
+21
-26
@@ -1,4 +1,4 @@
|
||||
iD.modes.MoveWay = function(wayId) {
|
||||
iD.modes.MoveWay = function(context, wayId) {
|
||||
var mode = {
|
||||
id: 'move-way'
|
||||
};
|
||||
@@ -6,55 +6,53 @@ iD.modes.MoveWay = function(wayId) {
|
||||
var keybinding = d3.keybinding('move-way');
|
||||
|
||||
mode.enter = function() {
|
||||
var map = mode.map,
|
||||
history = mode.history,
|
||||
graph = history.graph(),
|
||||
selection = map.surface,
|
||||
controller = mode.controller,
|
||||
projection = map.projection,
|
||||
way = graph.entity(wayId),
|
||||
origin = d3.mouse(selection.node()),
|
||||
annotation = t('operations.move.annotation.' + way.geometry(graph));
|
||||
var origin = point(),
|
||||
annotation = t('operations.move.annotation.' + context.geometry(wayId));
|
||||
|
||||
// If intiated via keyboard
|
||||
if (!origin[0] && !origin[1]) origin = null;
|
||||
|
||||
history.perform(
|
||||
context.perform(
|
||||
iD.actions.Noop(),
|
||||
annotation);
|
||||
|
||||
function point() {
|
||||
return d3.mouse(context.surface().node());
|
||||
}
|
||||
|
||||
function move() {
|
||||
var p = d3.mouse(selection.node()),
|
||||
var p = point(),
|
||||
delta = origin ?
|
||||
[p[0] - origin[0], p[1] - origin[1]] :
|
||||
[0, 0];
|
||||
|
||||
origin = p;
|
||||
|
||||
history.replace(
|
||||
iD.actions.MoveWay(wayId, delta, projection),
|
||||
context.replace(
|
||||
iD.actions.MoveWay(wayId, delta, context.projection),
|
||||
annotation);
|
||||
}
|
||||
|
||||
function finish() {
|
||||
d3.event.stopPropagation();
|
||||
controller.enter(iD.modes.Select([way.id], true));
|
||||
context.enter(iD.modes.Select(context, [wayId], true));
|
||||
}
|
||||
|
||||
function cancel() {
|
||||
history.pop();
|
||||
controller.enter(iD.modes.Select([way.id], true));
|
||||
context.pop();
|
||||
context.enter(iD.modes.Select(context, [wayId], true));
|
||||
}
|
||||
|
||||
function undone() {
|
||||
controller.enter(iD.modes.Browse());
|
||||
context.enter(iD.modes.Browse(context));
|
||||
}
|
||||
|
||||
selection
|
||||
context.selection()
|
||||
.on('mousemove.move-way', move)
|
||||
.on('click.move-way', finish);
|
||||
|
||||
history.on('undone.move-way', undone);
|
||||
context.history()
|
||||
.on('undone.move-way', undone);
|
||||
|
||||
keybinding
|
||||
.on('⎋', cancel)
|
||||
@@ -65,15 +63,12 @@ iD.modes.MoveWay = function(wayId) {
|
||||
};
|
||||
|
||||
mode.exit = function() {
|
||||
var map = mode.map,
|
||||
history = mode.history,
|
||||
selection = map.surface;
|
||||
|
||||
selection
|
||||
context.selection()
|
||||
.on('mousemove.move-way', null)
|
||||
.on('click.move-way', null);
|
||||
|
||||
history.on('undone.move-way', null);
|
||||
context.history()
|
||||
.on('undone.move-way', null);
|
||||
|
||||
keybinding.off();
|
||||
};
|
||||
|
||||
+38
-43
@@ -1,4 +1,4 @@
|
||||
iD.modes.Select = function(selection, initial) {
|
||||
iD.modes.Select = function(context, selection, initial) {
|
||||
var mode = {
|
||||
id: 'select',
|
||||
button: 'browse'
|
||||
@@ -6,12 +6,16 @@ iD.modes.Select = function(selection, initial) {
|
||||
|
||||
var inspector = iD.ui.inspector().initial(!!initial),
|
||||
keybinding = d3.keybinding('select'),
|
||||
behaviors,
|
||||
behaviors = [
|
||||
iD.behavior.Hover(),
|
||||
iD.behavior.Select(context),
|
||||
iD.behavior.DragNode(context),
|
||||
iD.behavior.DragMidpoint(context)],
|
||||
radialMenu;
|
||||
|
||||
function changeTags(d, tags) {
|
||||
if (!_.isEqual(singular().tags, tags)) {
|
||||
mode.history.perform(
|
||||
context.perform(
|
||||
iD.actions.ChangeTags(d.id, tags),
|
||||
t('operations.change_tags.annotation'));
|
||||
}
|
||||
@@ -19,7 +23,7 @@ iD.modes.Select = function(selection, initial) {
|
||||
|
||||
function singular() {
|
||||
if (selection.length === 1) {
|
||||
return mode.map.history().graph().entity(selection[0]);
|
||||
return context.entity(selection[0]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,24 +32,14 @@ iD.modes.Select = function(selection, initial) {
|
||||
};
|
||||
|
||||
mode.enter = function() {
|
||||
var map = mode.map,
|
||||
history = map.history(),
|
||||
graph = history.graph(),
|
||||
surface = map.surface,
|
||||
entity = singular();
|
||||
|
||||
behaviors = [
|
||||
iD.behavior.Hover(),
|
||||
iD.behavior.Select(mode),
|
||||
iD.behavior.DragNode(mode),
|
||||
iD.behavior.DragMidpoint(mode)];
|
||||
var entity = singular();
|
||||
|
||||
behaviors.forEach(function(behavior) {
|
||||
behavior(surface);
|
||||
context.install(behavior);
|
||||
});
|
||||
|
||||
var operations = d3.values(iD.operations)
|
||||
.map(function (o) { return o(selection, mode); })
|
||||
.map(function (o) { return o(selection, context); })
|
||||
.filter(function (o) { return o.available(); });
|
||||
|
||||
operations.forEach(function(operation) {
|
||||
@@ -62,9 +56,10 @@ iD.modes.Select = function(selection, initial) {
|
||||
}), true));
|
||||
|
||||
if (entity) {
|
||||
inspector.graph(graph);
|
||||
inspector.graph(context.graph());
|
||||
|
||||
d3.select('.inspector-wrap')
|
||||
context.container()
|
||||
.select('.inspector-wrap')
|
||||
.style('display', 'block')
|
||||
.style('opacity', 1)
|
||||
.datum(entity)
|
||||
@@ -73,38 +68,38 @@ iD.modes.Select = function(selection, initial) {
|
||||
if (d3.event) {
|
||||
// Pan the map if the clicked feature intersects with the position
|
||||
// of the inspector
|
||||
var inspector_size = d3.select('.inspector-wrap').size(),
|
||||
map_size = mode.map.size(),
|
||||
var inspector_size = context.container().select('.inspector-wrap').size(),
|
||||
map_size = context.map().size(),
|
||||
offset = 50,
|
||||
shift_left = d3.event.x - map_size[0] + inspector_size[0] + offset,
|
||||
center = (map_size[0] / 2) + shift_left + offset;
|
||||
|
||||
if (shift_left > 0 && inspector_size[1] > d3.event.y) {
|
||||
mode.map.centerEase(mode.map.projection.invert([center, map_size[1]/2]));
|
||||
context.map().centerEase(context.projection.invert([center, map_size[1]/2]));
|
||||
}
|
||||
}
|
||||
|
||||
inspector
|
||||
.on('changeTags', changeTags)
|
||||
.on('close', function() { mode.controller.enter(iD.modes.Browse()); });
|
||||
.on('close', function() { context.enter(iD.modes.Browse(context)); });
|
||||
|
||||
history.on('change.select', function() {
|
||||
context.history().on('change.select', function() {
|
||||
// Exit mode if selected entity gets undone
|
||||
var oldEntity = entity,
|
||||
newEntity = history.graph().entity(selection[0]);
|
||||
newEntity = context.entity(selection[0]);
|
||||
|
||||
if (!newEntity) {
|
||||
mode.controller.enter(iD.modes.Browse());
|
||||
context.enter(iD.modes.Browse(context));
|
||||
} else if (!_.isEqual(oldEntity.tags, newEntity.tags)) {
|
||||
inspector.tags(newEntity.tags);
|
||||
}
|
||||
|
||||
surface.call(radialMenu.close);
|
||||
context.surface().call(radialMenu.close);
|
||||
});
|
||||
}
|
||||
|
||||
map.on('move.select', function() {
|
||||
surface.call(radialMenu.close);
|
||||
context.map().on('move.select', function() {
|
||||
context.surface().call(radialMenu.close);
|
||||
});
|
||||
|
||||
function dblclick() {
|
||||
@@ -113,10 +108,10 @@ iD.modes.Select = function(selection, initial) {
|
||||
|
||||
if (datum instanceof iD.Way && !target.classed('fill')) {
|
||||
var choice = iD.geo.chooseIndex(datum,
|
||||
d3.mouse(mode.map.surface.node()), mode.map),
|
||||
d3.mouse(context.surface().node()), context.map()),
|
||||
node = iD.Node({ loc: choice.loc });
|
||||
|
||||
history.perform(
|
||||
context.perform(
|
||||
iD.actions.AddEntity(node),
|
||||
iD.actions.AddVertex(datum.id, node.id, choice.index),
|
||||
t('operations.add.annotation.vertex'));
|
||||
@@ -129,7 +124,8 @@ iD.modes.Select = function(selection, initial) {
|
||||
d3.select(document)
|
||||
.call(keybinding);
|
||||
|
||||
surface.on('dblclick.select', dblclick)
|
||||
context.surface()
|
||||
.on('dblclick.select', dblclick)
|
||||
.selectAll("*")
|
||||
.filter(function (d) { return d && selection.indexOf(d.id) >= 0; })
|
||||
.classed('selected', true);
|
||||
@@ -137,25 +133,23 @@ iD.modes.Select = function(selection, initial) {
|
||||
radialMenu = iD.ui.RadialMenu(operations);
|
||||
|
||||
if (d3.event && !initial) {
|
||||
var loc = map.mouseCoordinates();
|
||||
var loc = context.map().mouseCoordinates();
|
||||
|
||||
if (entity && entity.type === 'node') {
|
||||
loc = entity.loc;
|
||||
}
|
||||
|
||||
surface.call(radialMenu, map.projection(loc));
|
||||
context.surface().call(radialMenu, context.projection(loc));
|
||||
}
|
||||
};
|
||||
|
||||
mode.exit = function () {
|
||||
var surface = mode.map.surface,
|
||||
history = mode.history;
|
||||
|
||||
if (singular()) {
|
||||
changeTags(singular(), inspector.tags());
|
||||
}
|
||||
|
||||
d3.select('.inspector-wrap')
|
||||
context.container()
|
||||
.select('.inspector-wrap')
|
||||
.style('display', 'none')
|
||||
.html('');
|
||||
|
||||
@@ -164,7 +158,7 @@ iD.modes.Select = function(selection, initial) {
|
||||
d3.selectAll('div.typeahead').remove();
|
||||
|
||||
behaviors.forEach(function(behavior) {
|
||||
behavior.off(surface);
|
||||
context.uninstall(behavior);
|
||||
});
|
||||
|
||||
var q = iD.util.stringQs(location.hash.substring(1));
|
||||
@@ -172,13 +166,14 @@ iD.modes.Select = function(selection, initial) {
|
||||
|
||||
keybinding.off();
|
||||
|
||||
history.on('change.select', null);
|
||||
context.history()
|
||||
.on('change.select', null);
|
||||
|
||||
surface.on('dblclick.select', null)
|
||||
context.surface()
|
||||
.call(radialMenu.close)
|
||||
.on('dblclick.select', null)
|
||||
.selectAll(".selected")
|
||||
.classed('selected', false);
|
||||
|
||||
surface.call(radialMenu.close);
|
||||
};
|
||||
|
||||
return mode;
|
||||
|
||||
@@ -1,25 +1,19 @@
|
||||
iD.operations.Circularize = function(selection, mode) {
|
||||
iD.operations.Circularize = function(selection, context) {
|
||||
var entityId = selection[0],
|
||||
history = mode.map.history(),
|
||||
action = iD.actions.Circularize(entityId, mode.map);
|
||||
action = iD.actions.Circularize(entityId, context.map());
|
||||
|
||||
var operation = function() {
|
||||
var graph = history.graph(),
|
||||
entity = graph.entity(entityId),
|
||||
annotation = t('operations.circularize.annotation.' + entity.geometry(graph));
|
||||
|
||||
history.perform(action, annotation);
|
||||
var annotation = t('operations.circularize.annotation.' + context.geometry(entityId));
|
||||
context.perform(action, annotation);
|
||||
};
|
||||
|
||||
operation.available = function() {
|
||||
var graph = history.graph(),
|
||||
entity = graph.entity(entityId);
|
||||
return selection.length === 1 && entity.type === 'way';
|
||||
return selection.length === 1 &&
|
||||
context.entity(entityId).type === 'way';
|
||||
};
|
||||
|
||||
operation.enabled = function() {
|
||||
var graph = history.graph();
|
||||
return action.enabled(graph);
|
||||
return action.enabled(context.graph());
|
||||
};
|
||||
|
||||
operation.id = "circularize";
|
||||
|
||||
@@ -1,21 +1,18 @@
|
||||
iD.operations.Delete = function(selection, mode) {
|
||||
var entityId = selection[0],
|
||||
history = mode.map.history();
|
||||
iD.operations.Delete = function(selection, context) {
|
||||
var entityId = selection[0];
|
||||
|
||||
var operation = function() {
|
||||
var graph = history.graph(),
|
||||
entity = graph.entity(entityId),
|
||||
var entity = context.entity(entityId),
|
||||
action = {way: iD.actions.DeleteWay, node: iD.actions.DeleteNode}[entity.type],
|
||||
annotation = t('operations.delete.annotation.' + entity.geometry(graph));
|
||||
annotation = t('operations.delete.annotation.' + context.geometry(entityId));
|
||||
|
||||
history.perform(
|
||||
context.perform(
|
||||
action(entityId),
|
||||
annotation);
|
||||
};
|
||||
|
||||
operation.available = function() {
|
||||
var graph = history.graph(),
|
||||
entity = graph.entity(entityId);
|
||||
var entity = context.entity(entityId);
|
||||
return selection.length === 1 &&
|
||||
(entity.type === 'way' || entity.type === 'node');
|
||||
};
|
||||
|
||||
@@ -1,15 +1,13 @@
|
||||
iD.operations.Move = function(selection, mode) {
|
||||
var entityId = selection[0],
|
||||
history = mode.map.history();
|
||||
iD.operations.Move = function(selection, context) {
|
||||
var entityId = selection[0];
|
||||
|
||||
var operation = function() {
|
||||
mode.controller.enter(iD.modes.MoveWay(entityId));
|
||||
context.enter(iD.modes.MoveWay(context, entityId));
|
||||
};
|
||||
|
||||
operation.available = function() {
|
||||
var graph = history.graph();
|
||||
return selection.length === 1 &&
|
||||
graph.entity(entityId).type === 'way';
|
||||
context.entity(entityId).type === 'way';
|
||||
};
|
||||
|
||||
operation.enabled = function() {
|
||||
|
||||
@@ -1,18 +1,15 @@
|
||||
iD.operations.Reverse = function(selection, mode) {
|
||||
var entityId = selection[0],
|
||||
history = mode.map.history();
|
||||
iD.operations.Reverse = function(selection, context) {
|
||||
var entityId = selection[0];
|
||||
|
||||
var operation = function() {
|
||||
history.perform(
|
||||
context.perform(
|
||||
iD.actions.ReverseWay(entityId),
|
||||
t('operations.reverse.annotation'));
|
||||
};
|
||||
|
||||
operation.available = function() {
|
||||
var graph = history.graph(),
|
||||
entity = graph.entity(entityId);
|
||||
return selection.length === 1 &&
|
||||
entity.geometry(graph) === 'line';
|
||||
context.geometry(entityId) === 'line';
|
||||
};
|
||||
|
||||
operation.enabled = function() {
|
||||
|
||||
@@ -1,22 +1,18 @@
|
||||
iD.operations.Split = function(selection, mode) {
|
||||
iD.operations.Split = function(selection, context) {
|
||||
var entityId = selection[0],
|
||||
history = mode.map.history(),
|
||||
action = iD.actions.SplitWay(entityId);
|
||||
|
||||
var operation = function() {
|
||||
history.perform(action, t('operations.split.annotation'));
|
||||
context.perform(action, t('operations.split.annotation'));
|
||||
};
|
||||
|
||||
operation.available = function() {
|
||||
var graph = history.graph(),
|
||||
entity = graph.entity(entityId);
|
||||
return selection.length === 1 &&
|
||||
entity.geometry(graph) === 'vertex';
|
||||
context.geometry(entityId) === 'vertex';
|
||||
};
|
||||
|
||||
operation.enabled = function() {
|
||||
var graph = history.graph();
|
||||
return action.enabled(graph);
|
||||
return action.enabled(context.graph());
|
||||
};
|
||||
|
||||
operation.id = "split";
|
||||
|
||||
@@ -1,22 +1,18 @@
|
||||
iD.operations.Unjoin = function(selection, mode) {
|
||||
iD.operations.Unjoin = function(selection, context) {
|
||||
var entityId = selection[0],
|
||||
history = mode.map.history(),
|
||||
action = iD.actions.UnjoinNode(entityId);
|
||||
|
||||
var operation = function() {
|
||||
history.perform(action, 'Unjoined lines.');
|
||||
context.perform(action, 'Unjoined lines.');
|
||||
};
|
||||
|
||||
operation.available = function() {
|
||||
var graph = history.graph(),
|
||||
entity = graph.entity(entityId);
|
||||
return selection.length === 1 &&
|
||||
entity.geometry(graph) === 'vertex';
|
||||
context.geometry(entityId) === 'vertex';
|
||||
};
|
||||
|
||||
operation.enabled = function() {
|
||||
var graph = history.graph();
|
||||
return action.enabled(graph);
|
||||
return action.enabled(context.graph());
|
||||
};
|
||||
|
||||
operation.id = "unjoin";
|
||||
|
||||
+6
-23
@@ -1,11 +1,8 @@
|
||||
iD.ui.save = function() {
|
||||
|
||||
var map, controller;
|
||||
|
||||
function save(selection) {
|
||||
|
||||
var history = map.history(),
|
||||
connection = map.connection(),
|
||||
iD.ui.save = function(context) {
|
||||
return function (selection) {
|
||||
var map = context.map(),
|
||||
history = context.history(),
|
||||
connection = context.connection(),
|
||||
tooltip = bootstrap.tooltip()
|
||||
.placement('bottom');
|
||||
|
||||
@@ -60,7 +57,7 @@ iD.ui.save = function() {
|
||||
.on('fix', function(d) {
|
||||
map.extent(d.entity.extent(map.history().graph()));
|
||||
if (map.zoom() > 19) map.zoom(19);
|
||||
controller.enter(iD.modes.Select([d.entity.id]));
|
||||
context.enter(iD.modes.Select(context, [d.entity.id]));
|
||||
modal.remove();
|
||||
})
|
||||
.on('save', commit));
|
||||
@@ -88,19 +85,5 @@ iD.ui.save = function() {
|
||||
selection.call(tooltip.hide);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
save.map = function(_) {
|
||||
if (!arguments.length) return map;
|
||||
map = _;
|
||||
return save;
|
||||
};
|
||||
|
||||
save.controller = function(_) {
|
||||
if (!arguments.length) return controller;
|
||||
controller = _;
|
||||
return save;
|
||||
};
|
||||
|
||||
return save;
|
||||
};
|
||||
|
||||
+6
-5
@@ -119,6 +119,7 @@
|
||||
<script src='../js/id/graph/way.js'></script>
|
||||
|
||||
<script src='../js/id/connection.js'></script>
|
||||
<script src='../js/id/context.js'></script>
|
||||
<script src='../js/id/controller.js'></script>
|
||||
|
||||
<script src='../locale/locale.js'></script>
|
||||
@@ -150,9 +151,6 @@
|
||||
<script src="spec/actions/split_way.js"></script>
|
||||
<script src='spec/actions/unjoin_node.js'></script>
|
||||
|
||||
<script src="spec/behavior/hash.js"></script>
|
||||
<script src="spec/behavior/hover.js"></script>
|
||||
|
||||
<script src="spec/geo/extent.js"></script>
|
||||
|
||||
<script src="spec/graph/graph.js"></script>
|
||||
@@ -162,8 +160,6 @@
|
||||
<script src="spec/graph/relation.js"></script>
|
||||
<script src="spec/graph/history.js"></script>
|
||||
|
||||
<script src="spec/modes/add_point.js"></script>
|
||||
|
||||
<script src="spec/renderer/background.js"></script>
|
||||
<script src="spec/renderer/map.js"></script>
|
||||
|
||||
@@ -189,6 +185,11 @@
|
||||
<script src="spec/taginfo.js"></script>
|
||||
<script src="spec/util.js"></script>
|
||||
|
||||
<script src="spec/behavior/hash.js"></script>
|
||||
<script src="spec/behavior/hover.js"></script>
|
||||
|
||||
<script src="spec/modes/add_point.js"></script>
|
||||
|
||||
<script>
|
||||
(window.mochaPhantomJS || window.mocha).run();
|
||||
</script>
|
||||
|
||||
@@ -44,9 +44,6 @@
|
||||
<script src="spec/actions/split_way.js"></script>
|
||||
<script src='spec/actions/unjoin_node.js'></script>
|
||||
|
||||
<script src="spec/behavior/hash.js"></script>
|
||||
<script src="spec/behavior/hover.js"></script>
|
||||
|
||||
<script src="spec/geo/extent.js"></script>
|
||||
|
||||
<script src="spec/graph/graph.js"></script>
|
||||
@@ -56,8 +53,6 @@
|
||||
<script src="spec/graph/relation.js"></script>
|
||||
<script src="spec/graph/history.js"></script>
|
||||
|
||||
<script src="spec/modes/add_point.js"></script>
|
||||
|
||||
<script src="spec/renderer/background.js"></script>
|
||||
<script src="spec/renderer/map.js"></script>
|
||||
|
||||
@@ -83,6 +78,11 @@
|
||||
<script src="spec/taginfo.js"></script>
|
||||
<script src="spec/util.js"></script>
|
||||
|
||||
<script src="spec/behavior/hash.js"></script>
|
||||
<script src="spec/behavior/hover.js"></script>
|
||||
|
||||
<script src="spec/modes/add_point.js"></script>
|
||||
|
||||
<script>
|
||||
(window.mochaPhantomJS || window.mocha).run();
|
||||
</script>
|
||||
|
||||
+33
-37
@@ -1,19 +1,18 @@
|
||||
describe("iD.behavior.Hash", function () {
|
||||
var hash, map, controller;
|
||||
mocha.globals('__onhashchange.hash');
|
||||
|
||||
var hash, context;
|
||||
|
||||
beforeEach(function () {
|
||||
map = {
|
||||
on: function () { return map; },
|
||||
zoom: function () { return arguments.length ? map : 0; },
|
||||
center: function () { return arguments.length ? map : [0, 0]; },
|
||||
centerZoom: function () { return arguments.length ? map : [0, 0]; }
|
||||
};
|
||||
context = iD.Context();
|
||||
|
||||
controller = {
|
||||
on: function () { return controller; }
|
||||
};
|
||||
// Neuter connection
|
||||
context.connection().loadTiles = function () {};
|
||||
|
||||
hash = iD.behavior.Hash(controller, map);
|
||||
hash = iD.behavior.Hash(context);
|
||||
|
||||
d3.select(document.createElement('div'))
|
||||
.call(context.map());
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
@@ -22,44 +21,41 @@ describe("iD.behavior.Hash", function () {
|
||||
|
||||
it("sets hadHash if location.hash is present", function () {
|
||||
location.hash = "map=20.00/38.87952/-77.02405";
|
||||
|
||||
hash();
|
||||
|
||||
expect(hash.hadHash).to.be.true;
|
||||
});
|
||||
|
||||
it("centerZooms map to requested level", function () {
|
||||
location.hash = "map=20.00/38.87952/-77.02405";
|
||||
sinon.spy(map, 'centerZoom');
|
||||
|
||||
hash();
|
||||
expect(map.centerZoom).to.have.been.calledWith([-77.02405,38.87952], 20.0);
|
||||
|
||||
expect(context.map().center()[0]).to.be.closeTo(-77.02405, 0.1);
|
||||
expect(context.map().center()[1]).to.be.closeTo(38.87952, 0.1);
|
||||
expect(context.map().zoom()).to.equal(20.0);
|
||||
});
|
||||
|
||||
describe("on window hashchange events", function () {
|
||||
beforeEach(function () {
|
||||
hash();
|
||||
it("centerZooms map at requested coordinates on hash change", function (done) {
|
||||
hash();
|
||||
|
||||
d3.select(window).one('hashchange', function () {
|
||||
expect(context.map().center()[0]).to.be.closeTo(-77.02405, 0.1);
|
||||
expect(context.map().center()[1]).to.be.closeTo(38.87952, 0.1);
|
||||
expect(context.map().zoom()).to.equal(20.0);
|
||||
done();
|
||||
});
|
||||
|
||||
function onhashchange(fn) {
|
||||
d3.select(window).one("hashchange", fn);
|
||||
}
|
||||
|
||||
it("centerZooms map at requested coordinates", function (done) {
|
||||
onhashchange(function () {
|
||||
expect(map.centerZoom).to.have.been.calledWith([-77.02405,38.87952], 20.0);
|
||||
done();
|
||||
});
|
||||
|
||||
sinon.spy(map, 'centerZoom');
|
||||
location.hash = "#map=20.00/38.87952/-77.02405";
|
||||
});
|
||||
location.hash = "#map=20.00/38.87952/-77.02405";
|
||||
});
|
||||
|
||||
describe("on map move events", function () {
|
||||
it("stores the current zoom and coordinates in location.hash", function () {
|
||||
sinon.stub(map, 'on')
|
||||
.withArgs("move.hash", sinon.match.instanceOf(Function))
|
||||
.yields();
|
||||
hash();
|
||||
expect(location.hash).to.equal("#map=0.00/0/0");
|
||||
});
|
||||
it("stores the current zoom and coordinates in location.hash on map move events", function () {
|
||||
hash();
|
||||
|
||||
context.map().center([38.9, -77.0]);
|
||||
context.map().zoom(2.0);
|
||||
|
||||
expect(location.hash).to.equal("#map=2.00/-77.0/38.9");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,41 +1,36 @@
|
||||
describe("iD.modes.AddPoint", function () {
|
||||
var container, map, history, controller, mode;
|
||||
var context;
|
||||
|
||||
beforeEach(function () {
|
||||
container = d3.select('body').append('div');
|
||||
history = iD.History();
|
||||
map = iD.Map().history(history);
|
||||
controller = iD.Controller(map, history);
|
||||
var container = d3.select(document.createElement('div'));
|
||||
|
||||
container.call(map);
|
||||
container.append('div')
|
||||
context = iD.Context()
|
||||
.container(container);
|
||||
|
||||
container.call(context.map())
|
||||
.append('div')
|
||||
.attr('class', 'inspector-wrap');
|
||||
|
||||
mode = iD.modes.AddPoint();
|
||||
controller.enter(mode);
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
container.remove();
|
||||
context.enter(iD.modes.AddPoint(context));
|
||||
});
|
||||
|
||||
describe("clicking the map", function () {
|
||||
it("adds a node", function () {
|
||||
happen.click(map.surface.node(), {});
|
||||
expect(history.changes().created).to.have.length(1);
|
||||
happen.click(context.surface().node(), {});
|
||||
expect(context.changes().created).to.have.length(1);
|
||||
});
|
||||
|
||||
it("selects the node", function () {
|
||||
happen.click(map.surface.node(), {});
|
||||
expect(controller.mode.id).to.equal('select');
|
||||
expect(controller.mode.selection()).to.eql([history.changes().created[0].id]);
|
||||
happen.click(context.surface().node(), {});
|
||||
expect(context.mode().id).to.equal('select');
|
||||
expect(context.mode().selection()).to.eql([context.changes().created[0].id]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("pressing ⎋", function () {
|
||||
it("exits to browse mode", function () {
|
||||
happen.keydown(document, {keyCode: 27});
|
||||
expect(controller.mode.id).to.equal('browse');
|
||||
expect(context.mode().id).to.equal('browse');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -2,10 +2,13 @@ describe("iD.ui.confirm", function () {
|
||||
it('can be instantiated', function () {
|
||||
var confirm = iD.ui.confirm();
|
||||
expect(confirm).to.be.ok;
|
||||
happen.keydown(document, {keyCode: 27}); // dismiss
|
||||
});
|
||||
|
||||
it('can be dismissed', function () {
|
||||
var confirm = iD.ui.confirm();
|
||||
happen.click(confirm.select('button').node());
|
||||
expect(confirm.node().parentNode).to.be.null;
|
||||
happen.keydown(document, {keyCode: 27}); // dismiss
|
||||
});
|
||||
});
|
||||
|
||||
@@ -4,5 +4,6 @@ describe("iD.ui.modal", function () {
|
||||
.select('.content')
|
||||
.text('foo');
|
||||
expect(modal).to.be.ok;
|
||||
happen.keydown(document, {keyCode: 27}); // dismiss
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user