From 8eb04ddb4d301fa22647ff4a1c6701fcbfbed05d Mon Sep 17 00:00:00 2001
From: Tom MacWright
Date: Thu, 31 Jan 2013 19:41:52 -0500
Subject: [PATCH 01/50] combobox
---
combobox.html | 170 ++++++++++++++++++++++++++++++++++++++++++
css/app.css | 43 +++++++++++
js/lib/d3.combobox.js | 147 ++++++++++++++++++++++++++++++++++++
3 files changed, 360 insertions(+)
create mode 100644 combobox.html
create mode 100644 js/lib/d3.combobox.js
diff --git a/combobox.html b/combobox.html
new file mode 100644
index 000000000..0d97698b0
--- /dev/null
+++ b/combobox.html
@@ -0,0 +1,170 @@
+
+
+
+
+ iD
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/css/app.css b/css/app.css
index 4c149843d..2be1b819b 100644
--- a/css/app.css
+++ b/css/app.css
@@ -1267,3 +1267,46 @@ a.success-action {
.icon.icon-pre-text { margin-right: 0px;}
.save .label, .apply .label { display: block;}
}
+
+
+
+
+
+div.combobox {
+ width:155px;
+ z-index: 9999;
+ display: none;
+ box-shadow: 0 5px 10px 0 rgba(0,0,0,.2);
+ margin-top: -1px;
+ background: white;
+ max-height: 180px;
+ overflow: auto;
+ border: 1px solid #ccc;
+}
+
+div.combobox a {
+ height: 25px;
+ line-height: 25px;
+ cursor: pointer;
+ display: block;
+ border-top:1px solid #ccc;
+ background-color: #fff;
+ padding:1px 4px;
+ white-space: nowrap;
+}
+
+div.combobox a:hover,
+div.combobox a.selected {
+ background: #e1e8ff;
+ color: #154dff;
+}
+
+div.combobox a:first-child {
+ border-top: 0;
+}
+
+div.combobox-carat {
+ cursor: pointer;
+ padding:0 5px;
+ vertical-align:middle;
+}
diff --git a/js/lib/d3.combobox.js b/js/lib/d3.combobox.js
new file mode 100644
index 000000000..165456563
--- /dev/null
+++ b/js/lib/d3.combobox.js
@@ -0,0 +1,147 @@
+d3.combobox = function() {
+ var event = d3.dispatch('accept'),
+ autohighlight = false,
+ autofilter = false,
+ input,
+ container,
+ data;
+
+ var typeahead = function(selection) {
+ var hidden, idx = autohighlight ? 0 : -1;
+
+ var rect = selection.select('input').node().getBoundingClientRect();
+
+ input = selection.select('input');
+
+ container = selection
+ .insert('div', ':first-child')
+ .attr('class', 'combobox')
+ .style({
+ position: 'absolute',
+ display: 'none',
+ left: '0px',
+ width: rect.width + 'px',
+ top: rect.height + 'px'
+ });
+
+ carat = selection
+ .insert('div', ':first-child')
+ .attr('class', 'combobox-carat')
+ .text('+')
+ .style({
+ position: 'absolute',
+ left: (rect.width - 20) + 'px',
+ top: '0px'
+ })
+ .on('click', function() {
+ update();
+ show();
+ });
+
+ selection
+ .on('keyup.typeahead', key);
+
+ hidden = false;
+
+ function hide() {
+ idx = autohighlight ? 0 : -1;
+ hidden = true;
+ }
+
+ function show() {
+ container.style('display', 'block');
+ }
+
+ function slowHide() {
+ if (autohighlight && container.select('a.selected').node()) {
+ select(container.select('a.selected').datum());
+ event.accept();
+ }
+ window.setTimeout(hide, 150);
+ }
+
+ selection
+ .on('focus.typeahead', show)
+ .on('blur.typeahead', slowHide);
+
+ function key() {
+ var len = container.selectAll('a').data().length;
+ if (d3.event.keyCode === 40) {
+ idx = Math.min(idx + 1, len - 1);
+ return highlight();
+ } else if (d3.event.keyCode === 38) {
+ idx = Math.max(idx - 1, 0);
+ return highlight();
+ } else if (d3.event.keyCode === 13) {
+ if (container.select('a.selected').node()) {
+ select(container.select('a.selected').datum());
+ }
+ event.accept();
+ hide();
+ } else {
+ update();
+ }
+ }
+
+ function highlight() {
+ container
+ .selectAll('a')
+ .classed('selected', function(d, i) { return i == idx; });
+ }
+
+ function update() {
+
+ function run(data) {
+ container.style('display', function() {
+ return data.length ? 'block' : 'none';
+ });
+
+ var options = container
+ .selectAll('a')
+ .data(data, function(d) { return d.value; });
+
+ options.enter()
+ .append('a')
+ .text(function(d) { return d.value; })
+ .attr('title', function(d) { return d.title; })
+ .on('click', select);
+
+ options.exit().remove();
+
+ options
+ .classed('selected', function(d, i) { return i == idx; });
+ }
+
+ if (typeof data === 'function') data(selection, run);
+ else run(data);
+ }
+
+ function select(d) {
+ input
+ .property('value', d.value)
+ .trigger('change');
+ container.style('display', 'none');
+ }
+
+ };
+
+ typeahead.data = function(_) {
+ if (!arguments.length) return data;
+ data = _;
+ return typeahead;
+ };
+
+ typeahead.autofilter = function(_) {
+ if (!arguments.length) return autofilter;
+ autofilter = _;
+ return typeahead;
+ };
+
+ typeahead.autohighlight = function(_) {
+ if (!arguments.length) return autohighlight;
+ autohighlight = _;
+ return typeahead;
+ };
+
+ return d3.rebind(typeahead, event, 'on');
+};
From 9494d8d468fd188bae5687703e8036488bc01c7c Mon Sep 17 00:00:00 2001
From: John Firebaugh
Date: Fri, 1 Feb 2013 10:16:18 -0500
Subject: [PATCH 02/50] Remove unused
---
js/id/renderer/map.js | 18 ------------------
1 file changed, 18 deletions(-)
diff --git a/js/id/renderer/map.js b/js/id/renderer/map.js
index a2c4781ef..c02ff65cb 100644
--- a/js/id/renderer/map.js
+++ b/js/id/renderer/map.js
@@ -369,24 +369,6 @@ iD.Map = function() {
return map;
};
- map.hint = function (_) {
- if (_ === false) {
- d3.select('div.inspector-wrap')
- .style('opacity', 0)
- .style('display', 'none');
- } else {
- d3.select('div.inspector-wrap')
- .html('')
- .style('display', 'block')
- .transition()
- .style('opacity', 1);
- d3.select('div.inspector-wrap')
- .append('div')
- .attr('class','inspector-inner')
- .text(_);
- }
- };
-
map.editable = function() {
return map.zoom() >= 16;
};
From 559f3c9037f1e87ce87c7edbd5a30fdb4f04abec Mon Sep 17 00:00:00 2001
From: Ansis Brammanis
Date: Fri, 1 Feb 2013 11:00:55 -0500
Subject: [PATCH 03/50] Remove unecessary line
---
js/id/renderer/map.js | 1 -
1 file changed, 1 deletion(-)
diff --git a/js/id/renderer/map.js b/js/id/renderer/map.js
index c02ff65cb..cd99de738 100644
--- a/js/id/renderer/map.js
+++ b/js/id/renderer/map.js
@@ -55,7 +55,6 @@ iD.Map = function() {
function pxCenter() { return [dimensions[0] / 2, dimensions[1] / 2]; }
function drawVector(difference) {
- if (surface.style(transformProp) != 'none') return;
var filter, all,
extent = map.extent(),
graph = history.graph();
From ab7290a86595c2c3a440c2921200bb08413e9392 Mon Sep 17 00:00:00 2001
From: Tom MacWright
Date: Fri, 1 Feb 2013 11:31:31 -0500
Subject: [PATCH 04/50] Fix re-requesting failed tiles. Fixes #594
---
js/id/renderer/background.js | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/js/id/renderer/background.js b/js/id/renderer/background.js
index 54e3835ee..cae44ca09 100644
--- a/js/id/renderer/background.js
+++ b/js/id/renderer/background.js
@@ -83,7 +83,10 @@ iD.Background = function() {
}
});
- requests = uniqueBy(requests, 3);
+ requests = uniqueBy(requests, 3).filter(function(r) {
+ // don't re-request tiles which have failed in the past
+ return cache[r[3]] !== false;
+ });
function load(d) {
cache[d[3]] = true;
@@ -125,7 +128,7 @@ iD.Background = function() {
.attr('src', function(d) { return d[3]; })
.on('error', error)
.on('load', load);
-
+
image.style(transformProp, imageTransform);
if (Object.keys(cache).length > 100) cache = {};
From 7e68e8e114020da318e33537cce9d57d1698cfeb Mon Sep 17 00:00:00 2001
From: John Firebaugh
Date: Thu, 31 Jan 2013 15:50:00 -0500
Subject: [PATCH 05/50] 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.
---
Makefile | 1 +
index.html | 3 +-
js/id/behavior/add_way.js | 18 ++++----
js/id/behavior/drag_midpoint.js | 15 +++---
js/id/behavior/drag_node.js | 22 ++++-----
js/id/behavior/draw.js | 24 +++++-----
js/id/behavior/draw_way.js | 69 ++++++++++++++--------------
js/id/behavior/hash.js | 29 ++++++------
js/id/behavior/select.js | 8 ++--
js/id/context.js | 44 ++++++++++++++++++
js/id/controller.js | 6 +--
js/id/id.js | 39 ++++++++++------
js/id/modes/add_area.js | 38 +++++++---------
js/id/modes/add_line.js | 42 ++++++++---------
js/id/modes/add_point.js | 25 ++++------
js/id/modes/browse.js | 22 ++++-----
js/id/modes/draw_area.js | 12 ++---
js/id/modes/draw_line.js | 12 ++---
js/id/modes/move_way.js | 47 +++++++++----------
js/id/modes/select.js | 81 ++++++++++++++++-----------------
js/id/operations/circularize.js | 20 +++-----
js/id/operations/delete.js | 15 +++---
js/id/operations/move.js | 10 ++--
js/id/operations/reverse.js | 11 ++---
js/id/operations/split.js | 12 ++---
js/id/operations/unjoin.js | 12 ++---
js/id/ui/save.js | 29 +++---------
test/index.html | 11 +++--
test/index_packaged.html | 10 ++--
test/spec/behavior/hash.js | 70 ++++++++++++++--------------
test/spec/modes/add_point.js | 33 ++++++--------
test/spec/ui/confirm.js | 3 ++
test/spec/ui/modal.js | 1 +
33 files changed, 384 insertions(+), 410 deletions(-)
create mode 100644 js/id/context.js
diff --git a/Makefile b/Makefile
index 1db4f2efb..598bce278 100644
--- a/Makefile
+++ b/Makefile
@@ -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 \
diff --git a/index.html b/index.html
index c8ddd7562..306575804 100644
--- a/index.html
+++ b/index.html
@@ -122,9 +122,10 @@
+
+
-
diff --git a/js/id/behavior/add_way.js b/js/id/behavior/add_way.js
index 89ba7f1cd..207c88566 100644
--- a/js/id/behavior/add_way.js
+++ b/js/id/behavior/add_way.js
@@ -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');
diff --git a/js/id/behavior/drag_midpoint.js b/js/id/behavior/drag_midpoint.js
index 6041946cd..42099963c 100644
--- a/js/id/behavior/drag_midpoint.js
+++ b/js/id/behavior/drag_midpoint.js
@@ -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'));
});
diff --git a/js/id/behavior/drag_node.js b/js/id/behavior/drag_node.js
index b9846617d..b62162e94 100644
--- a/js/id/behavior/drag_node.js
+++ b/js/id/behavior/drag_node.js
@@ -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));
});
diff --git a/js/id/behavior/draw.js b/js/id/behavior/draw.js
index bce4470b6..8405ac341 100644
--- a/js/id/behavior/draw.js
+++ b/js/id/behavior/draw.js
@@ -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)
diff --git a/js/id/behavior/draw_way.js b/js/id/behavior/draw_way.js
index 1cc62b755..28a8fbb38 100644
--- a/js/id/behavior/draw_way.js
+++ b/js/id/behavior/draw_way.js
@@ -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');
diff --git a/js/id/behavior/hash.js b/js/id/behavior/hash.js
index 65e748e28..871b73a35 100644
--- a/js/id/behavior/hash.js
+++ b/js/id/behavior/hash.js
@@ -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);
diff --git a/js/id/behavior/select.js b/js/id/behavior/select.js
index cee2cc940..e078fdbf1 100644
--- a/js/id/behavior/select.js
+++ b/js/id/behavior/select.js
@@ -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));
}
}
diff --git a/js/id/context.js b/js/id/context.js
new file mode 100644
index 000000000..60f878b32
--- /dev/null
+++ b/js/id/context.js
@@ -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;
+};
diff --git a/js/id/controller.js b/js/id/controller.js
index 6c4e0fd1e..af1e7c388 100644
--- a/js/id/controller.js
+++ b/js/id/controller.js
@@ -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);
diff --git a/js/id/id.js b/js/id/id.js
index 3e8aabcc3..3c2d0c482 100644
--- a/js/id/id.js
+++ b/js/id/id.js
@@ -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();
diff --git a/js/id/modes/add_area.js b/js/id/modes/add_area.js
index bda4e0daa..ae2e008ee 100644
--- a/js/id/modes/add_area.js
+++ b/js/id/modes/add_area.js
@@ -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;
diff --git a/js/id/modes/add_line.js b/js/id/modes/add_line.js
index 92e9a64d7..79c5f3031 100644
--- a/js/id/modes/add_line.js
+++ b/js/id/modes/add_line.js
@@ -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;
diff --git a/js/id/modes/add_point.js b/js/id/modes/add_point.js
index 6dd524bb5..c3dc7f075 100644
--- a/js/id/modes/add_point.js
+++ b/js/id/modes/add_point.js
@@ -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;
diff --git a/js/id/modes/browse.js b/js/id/modes/browse.js
index 7652576ea..33add1262 100644
--- a/js/id/modes/browse.js
+++ b/js/id/modes/browse.js
@@ -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);
});
};
diff --git a/js/id/modes/draw_area.js b/js/id/modes/draw_area.js
index 9801a092c..aee2f153c 100644
--- a/js/id/modes/draw_area.js
+++ b/js/id/modes/draw_area.js
@@ -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;
diff --git a/js/id/modes/draw_line.js b/js/id/modes/draw_line.js
index 5ae8c2703..9fd07c937 100644
--- a/js/id/modes/draw_line.js
+++ b/js/id/modes/draw_line.js
@@ -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;
diff --git a/js/id/modes/move_way.js b/js/id/modes/move_way.js
index 5c262e259..30c473406 100644
--- a/js/id/modes/move_way.js
+++ b/js/id/modes/move_way.js
@@ -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();
};
diff --git a/js/id/modes/select.js b/js/id/modes/select.js
index 8d29450d6..df445862d 100644
--- a/js/id/modes/select.js
+++ b/js/id/modes/select.js
@@ -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;
diff --git a/js/id/operations/circularize.js b/js/id/operations/circularize.js
index 4b0f27bf9..419a6e9eb 100644
--- a/js/id/operations/circularize.js
+++ b/js/id/operations/circularize.js
@@ -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";
diff --git a/js/id/operations/delete.js b/js/id/operations/delete.js
index 12df22a09..d631a2ed7 100644
--- a/js/id/operations/delete.js
+++ b/js/id/operations/delete.js
@@ -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');
};
diff --git a/js/id/operations/move.js b/js/id/operations/move.js
index 10405cc53..d9da39f64 100644
--- a/js/id/operations/move.js
+++ b/js/id/operations/move.js
@@ -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() {
diff --git a/js/id/operations/reverse.js b/js/id/operations/reverse.js
index 78b8789dd..77bacc64e 100644
--- a/js/id/operations/reverse.js
+++ b/js/id/operations/reverse.js
@@ -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() {
diff --git a/js/id/operations/split.js b/js/id/operations/split.js
index 4274fc41b..0d7ff6ae4 100644
--- a/js/id/operations/split.js
+++ b/js/id/operations/split.js
@@ -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";
diff --git a/js/id/operations/unjoin.js b/js/id/operations/unjoin.js
index 2a40ec067..d4fcc1426 100644
--- a/js/id/operations/unjoin.js
+++ b/js/id/operations/unjoin.js
@@ -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";
diff --git a/js/id/ui/save.js b/js/id/ui/save.js
index b8085e21a..6098519da 100644
--- a/js/id/ui/save.js
+++ b/js/id/ui/save.js
@@ -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;
};
diff --git a/test/index.html b/test/index.html
index b85eb1b56..b56645ee7 100644
--- a/test/index.html
+++ b/test/index.html
@@ -119,6 +119,7 @@
+
@@ -150,9 +151,6 @@
-
-
-
@@ -162,8 +160,6 @@
-
-
@@ -189,6 +185,11 @@
+
+
+
+
+
diff --git a/test/index_packaged.html b/test/index_packaged.html
index 60979e236..11f8368f4 100644
--- a/test/index_packaged.html
+++ b/test/index_packaged.html
@@ -44,9 +44,6 @@
-
-
-
@@ -56,8 +53,6 @@
-
-
@@ -83,6 +78,11 @@
+
+
+
+
+
diff --git a/test/spec/behavior/hash.js b/test/spec/behavior/hash.js
index 7616bf536..5aceb53fc 100644
--- a/test/spec/behavior/hash.js
+++ b/test/spec/behavior/hash.js
@@ -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");
});
});
diff --git a/test/spec/modes/add_point.js b/test/spec/modes/add_point.js
index a284cf682..5c544c0c5 100644
--- a/test/spec/modes/add_point.js
+++ b/test/spec/modes/add_point.js
@@ -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');
});
});
});
diff --git a/test/spec/ui/confirm.js b/test/spec/ui/confirm.js
index a9380e1cc..428a8aa6c 100644
--- a/test/spec/ui/confirm.js
+++ b/test/spec/ui/confirm.js
@@ -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
});
});
diff --git a/test/spec/ui/modal.js b/test/spec/ui/modal.js
index 32a42878a..d7f818d80 100644
--- a/test/spec/ui/modal.js
+++ b/test/spec/ui/modal.js
@@ -4,5 +4,6 @@ describe("iD.ui.modal", function () {
.select('.content')
.text('foo');
expect(modal).to.be.ok;
+ happen.keydown(document, {keyCode: 27}); // dismiss
});
});
From 579d6325636938443f34837fc05dd856db65539f Mon Sep 17 00:00:00 2001
From: John Firebaugh
Date: Thu, 31 Jan 2013 17:19:01 -0500
Subject: [PATCH 06/50] Hoist functions up a scope
---
js/id/modes/add_area.js | 120 +++++++++++++++++------------------
js/id/modes/add_line.js | 134 +++++++++++++++++++--------------------
js/id/modes/add_point.js | 62 +++++++++---------
3 files changed, 155 insertions(+), 161 deletions(-)
diff --git a/js/id/modes/add_area.js b/js/id/modes/add_area.js
index ae2e008ee..0a9496bb6 100644
--- a/js/id/modes/add_area.js
+++ b/js/id/modes/add_area.js
@@ -7,71 +7,69 @@ iD.modes.AddArea = function(context) {
key: t('modes.add_area.key')
};
- var behavior,
- defaultTags = {area: 'yes'};
-
- mode.enter = function() {
- function start(loc) {
- var graph = context.graph(),
- node = iD.Node({loc: loc}),
- way = iD.Way({tags: defaultTags});
-
- context.perform(
- iD.actions.AddEntity(node),
- iD.actions.AddEntity(way),
- iD.actions.AddVertex(way.id, node.id),
- iD.actions.AddVertex(way.id, node.id));
-
- context.enter(iD.modes.DrawArea(context, way.id, graph));
- }
-
- function startFromWay(other, loc, index) {
- var graph = context.graph(),
- node = iD.Node({loc: loc}),
- way = iD.Way({tags: defaultTags});
-
- 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));
-
- context.enter(iD.modes.DrawArea(context, way.id, graph));
- }
-
- function startFromNode(node) {
- var graph = context.graph(),
- way = iD.Way({tags: defaultTags});
-
- context.perform(
- iD.actions.AddEntity(way),
- iD.actions.AddVertex(way.id, node.id),
- iD.actions.AddVertex(way.id, node.id));
-
- context.enter(iD.modes.DrawArea(context, way.id, graph));
- }
-
- function startFromMidpoint(midpoint) {
- var graph = context.graph(),
- node = iD.Node(),
- way = iD.Way({tags: defaultTags});
-
- 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));
-
- context.enter(iD.modes.DrawArea(context, way.id, graph));
- }
-
- behavior = iD.behavior.AddWay(context)
+ var behavior = iD.behavior.AddWay(context)
.on('start', start)
.on('startFromWay', startFromWay)
.on('startFromNode', startFromNode)
- .on('startFromMidpoint', startFromMidpoint);
+ .on('startFromMidpoint', startFromMidpoint),
+ defaultTags = {area: 'yes'};
+ function start(loc) {
+ var graph = context.graph(),
+ node = iD.Node({loc: loc}),
+ way = iD.Way({tags: defaultTags});
+
+ context.perform(
+ iD.actions.AddEntity(node),
+ iD.actions.AddEntity(way),
+ iD.actions.AddVertex(way.id, node.id),
+ iD.actions.AddVertex(way.id, node.id));
+
+ context.enter(iD.modes.DrawArea(context, way.id, graph));
+ }
+
+ function startFromWay(other, loc, index) {
+ var graph = context.graph(),
+ node = iD.Node({loc: loc}),
+ way = iD.Way({tags: defaultTags});
+
+ 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));
+
+ context.enter(iD.modes.DrawArea(context, way.id, graph));
+ }
+
+ function startFromNode(node) {
+ var graph = context.graph(),
+ way = iD.Way({tags: defaultTags});
+
+ context.perform(
+ iD.actions.AddEntity(way),
+ iD.actions.AddVertex(way.id, node.id),
+ iD.actions.AddVertex(way.id, node.id));
+
+ context.enter(iD.modes.DrawArea(context, way.id, graph));
+ }
+
+ function startFromMidpoint(midpoint) {
+ var graph = context.graph(),
+ node = iD.Node(),
+ way = iD.Way({tags: defaultTags});
+
+ 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));
+
+ context.enter(iD.modes.DrawArea(context, way.id, graph));
+ }
+
+ mode.enter = function() {
context.install(behavior);
context.tail(t('modes.add_area.tail'));
};
diff --git a/js/id/modes/add_line.js b/js/id/modes/add_line.js
index 79c5f3031..7845e6e6f 100644
--- a/js/id/modes/add_line.js
+++ b/js/id/modes/add_line.js
@@ -7,78 +7,76 @@ iD.modes.AddLine = function(context) {
key: t('modes.add_line.key')
};
- var behavior,
- defaultTags = {highway: 'residential'};
-
- mode.enter = function() {
- function start(loc) {
- var graph = context.graph(),
- node = iD.Node({loc: loc}),
- way = iD.Way({tags: defaultTags});
-
- context.perform(
- iD.actions.AddEntity(node),
- iD.actions.AddEntity(way),
- iD.actions.AddVertex(way.id, node.id));
-
- context.enter(iD.modes.DrawLine(context, way.id, 'forward', graph));
- }
-
- function startFromWay(other, loc, index) {
- var graph = context.graph(),
- node = iD.Node({loc: loc}),
- way = iD.Way({tags: defaultTags});
-
- 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));
-
- context.enter(iD.modes.DrawLine(context, way.id, 'forward', graph));
- }
-
- function startFromNode(node) {
- var graph = context.graph(),
- parent = graph.parentWays(node)[0],
- isLine = parent && parent.geometry(graph) === 'line';
-
- if (isLine && parent.first() === node.id) {
- context.enter(iD.modes.DrawLine(context, parent.id, 'backward', graph));
-
- } else if (isLine && parent.last() === node.id) {
- context.enter(iD.modes.DrawLine(context, parent.id, 'forward', graph));
-
- } else {
- var way = iD.Way({tags: defaultTags});
-
- context.perform(
- iD.actions.AddEntity(way),
- iD.actions.AddVertex(way.id, node.id));
-
- context.enter(iD.modes.DrawLine(context, way.id, 'forward', graph));
- }
- }
-
- function startFromMidpoint(midpoint) {
- var graph = context.graph(),
- node = iD.Node(),
- way = iD.Way({tags: defaultTags});
-
- context.perform(
- iD.actions.AddMidpoint(midpoint, node),
- iD.actions.AddEntity(way),
- iD.actions.AddVertex(way.id, node.id));
-
- context.enter(iD.modes.DrawLine(context, way.id, 'forward', graph));
- }
-
- behavior = iD.behavior.AddWay(context)
+ var behavior = iD.behavior.AddWay(context)
.on('start', start)
.on('startFromWay', startFromWay)
.on('startFromNode', startFromNode)
- .on('startFromMidpoint', startFromMidpoint);
+ .on('startFromMidpoint', startFromMidpoint),
+ defaultTags = {highway: 'residential'};
+ function start(loc) {
+ var graph = context.graph(),
+ node = iD.Node({loc: loc}),
+ way = iD.Way({tags: defaultTags});
+
+ context.perform(
+ iD.actions.AddEntity(node),
+ iD.actions.AddEntity(way),
+ iD.actions.AddVertex(way.id, node.id));
+
+ context.enter(iD.modes.DrawLine(context, way.id, 'forward', graph));
+ }
+
+ function startFromWay(other, loc, index) {
+ var graph = context.graph(),
+ node = iD.Node({loc: loc}),
+ way = iD.Way({tags: defaultTags});
+
+ 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));
+
+ context.enter(iD.modes.DrawLine(context, way.id, 'forward', graph));
+ }
+
+ function startFromNode(node) {
+ var graph = context.graph(),
+ parent = graph.parentWays(node)[0],
+ isLine = parent && parent.geometry(graph) === 'line';
+
+ if (isLine && parent.first() === node.id) {
+ context.enter(iD.modes.DrawLine(context, parent.id, 'backward', graph));
+
+ } else if (isLine && parent.last() === node.id) {
+ context.enter(iD.modes.DrawLine(context, parent.id, 'forward', graph));
+
+ } else {
+ var way = iD.Way({tags: defaultTags});
+
+ context.perform(
+ iD.actions.AddEntity(way),
+ iD.actions.AddVertex(way.id, node.id));
+
+ context.enter(iD.modes.DrawLine(context, way.id, 'forward', graph));
+ }
+ }
+
+ function startFromMidpoint(midpoint) {
+ var graph = context.graph(),
+ node = iD.Node(),
+ way = iD.Way({tags: defaultTags});
+
+ context.perform(
+ iD.actions.AddMidpoint(midpoint, node),
+ iD.actions.AddEntity(way),
+ iD.actions.AddVertex(way.id, node.id));
+
+ context.enter(iD.modes.DrawLine(context, way.id, 'forward', graph));
+ }
+
+ mode.enter = function() {
context.install(behavior);
context.tail(t('modes.add_line.tail'));
};
diff --git a/js/id/modes/add_point.js b/js/id/modes/add_point.js
index c3dc7f075..5a24dad25 100644
--- a/js/id/modes/add_point.js
+++ b/js/id/modes/add_point.js
@@ -6,46 +6,44 @@ iD.modes.AddPoint = function(context) {
key: t('modes.add_point.key')
};
- var behavior;
+ var behavior = iD.behavior.Draw(context)
+ .on('click', add)
+ .on('clickWay', addWay)
+ .on('clickNode', addNode)
+ .on('clickMidpoint', addNode)
+ .on('cancel', cancel)
+ .on('finish', cancel);
+
+ function add(loc) {
+ var node = iD.Node({loc: loc});
+
+ context.perform(
+ iD.actions.AddEntity(node),
+ t('operations.add.annotation.point'));
+
+ context.enter(iD.modes.Select(context, [node.id], true));
+ }
+
+ function addWay(way, loc, index) {
+ add(loc);
+ }
+
+ function addNode(node) {
+ add(node.loc);
+ }
+
+ function cancel() {
+ context.enter(iD.modes.Browse(context));
+ }
mode.enter = function() {
- function add(loc) {
- var node = iD.Node({loc: loc});
-
- context.perform(
- iD.actions.AddEntity(node),
- t('operations.add.annotation.point'));
-
- context.enter(iD.modes.Select(context, [node.id], true));
- }
-
- function addWay(way, loc, index) {
- add(loc);
- }
-
- function addNode(node) {
- add(node.loc);
- }
-
- function cancel() {
- context.enter(iD.modes.Browse(context));
- }
-
- behavior = iD.behavior.Draw(context)
- .on('click', add)
- .on('clickWay', addWay)
- .on('clickNode', addNode)
- .on('clickMidpoint', addNode)
- .on('cancel', cancel)
- .on('finish', cancel);
-
context.install(behavior);
context.tail(t('modes.add_point.tail'));
};
mode.exit = function() {
- context.tail(false);
context.uninstall(behavior);
+ context.tail(false);
};
return mode;
From 000ceb6467d7c79e22522a2575b413bd8d09b8f3 Mon Sep 17 00:00:00 2001
From: John Firebaugh
Date: Fri, 1 Feb 2013 11:36:53 -0500
Subject: [PATCH 07/50] iD.Context -> iD
All the UI setup code moved to iD.ui.
---
Makefile | 1 -
index.html | 9 +-
index_packaged.html | 14 +-
js/id/context.js | 44 -----
js/id/id.js | 323 +++++------------------------------
js/id/ui.js | 257 +++++++++++++++++++++++++++-
test/index.html | 1 -
test/spec/behavior/hash.js | 2 +-
test/spec/modes/add_point.js | 2 +-
9 files changed, 319 insertions(+), 334 deletions(-)
delete mode 100644 js/id/context.js
diff --git a/Makefile b/Makefile
index 598bce278..1db4f2efb 100644
--- a/Makefile
+++ b/Makefile
@@ -27,7 +27,6 @@ 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 \
diff --git a/index.html b/index.html
index 306575804..ab6070fbc 100644
--- a/index.html
+++ b/index.html
@@ -123,7 +123,6 @@
-
@@ -135,9 +134,13 @@
locale.current = 'en';
d3.json('keys.json', function(err, keys) {
var id = iD();
- id.connection().keys(keys)
+
+ id.connection()
+ .keys(keys)
.url('http://api06.dev.openstreetmap.org');
- d3.select("#iD").call(id);
+
+ d3.select("#iD")
+ .call(id.ui())
});