diff --git a/index.html b/index.html
index 7b384ffce..9e59359cd 100755
--- a/index.html
+++ b/index.html
@@ -70,7 +70,19 @@
iD.Hash().map(map);
iD.UI.bind();
- iD.controller(map);
+ var controller = iD.controller(map);
+
+ d3.selectAll('button#place').on('click', function() {
+ controller.go(iD.actions.AddPlace);
+ });
+
+ d3.selectAll('button#road').on('click', function() {
+ controller.go(iD.actions.AddRoad);
+ });
+
+ d3.selectAll('button#area').on('click', function() {
+ controller.go(iD.actions.AddArea);
+ });
window.onresize = function() {
map.setSize(m.node().offsetWidth,
diff --git a/js/iD/actions/actions.js b/js/iD/actions/actions.js
index 2584b35ed..18efa77ee 100644
--- a/js/iD/actions/actions.js
+++ b/js/iD/actions/actions.js
@@ -1,13 +1,6 @@
iD.actions = {};
iD.actions.AddPlace = {
- bind: function(controller, map) {
- this.controller = controller;
- this.map = map;
- d3.selectAll('button#place').on('click', function() {
- iD.actions.AddPlace.enter();
- });
- },
node: function(ll) {
return {
type: 'node',
@@ -56,30 +49,125 @@ iD.actions.AddPlace = {
};
iD.actions.AddRoad = {
- bind: function(controller, map) {
- this.controller = controller;
- this.map = map;
- d3.selectAll('button#road').on('click', function() {
- iD.actions.AddRoad.enter();
- });
+ node: function(ll) {
+ return {
+ type: 'node',
+ lat: ll[1],
+ lon: ll[0],
+ id: iD.Util.id(),
+ tags: {}
+ };
+ },
+ way: function(ll) {
+ return {
+ type: 'way',
+ nodes: [],
+ tags: {
+ highway: 'residential'
+ },
+ id: iD.Util.id()
+ };
},
enter: function() {
d3.selectAll('button').classed('active', false);
d3.selectAll('button#road').classed('active', true);
+
+ var surface = this.map.surface;
+ var teaser = surface.selectAll('g#temp-g')
+ .append('g').attr('id', 'addroad');
+
+ teaser.append('circle')
+ .attr('class', 'teaser-point')
+ .attr('r', 10);
+
+ surface.on('mousemove.addroad', function() {
+ teaser.attr('transform', function() {
+ var off = d3.mouse(surface.node());
+ return 'translate(' + off + ')';
+ });
+ });
+
+ surface.on('click.addroad', function() {
+ var ll = this.map.projection.invert(
+ d3.mouse(surface.node()));
+ var way = this.way();
+ var node = this.node(ll);
+ way.nodes.push(node.id);
+ iD.operations.changeWayNodes(this.map, way, node);
+ this.controller.go(iD.actions.DrawRoad(way));
+ this.exit();
+ }.bind(this));
+
+ d3.select(document).on('keydown.addplace', function() {
+ if (d3.event.keyCode === 27) this.exit();
+ }.bind(this));
},
exit: function() {
+ this.map.surface.on('.addroad', null);
+ d3.select(document).on('.addroad', null);
+ d3.selectAll('#addroad').remove();
d3.selectAll('button#road').classed('active', false);
}
};
+iD.actions.DrawRoad = function(way) {
+ return {
+ node: function(ll) {
+ return {
+ type: 'node',
+ lat: ll[1],
+ lon: ll[0],
+ id: iD.Util.id(),
+ tags: {}
+ };
+ },
+ enter: function() {
+ var surface = this.map.surface;
+
+ this.falsenode = this.node([0, 0]);
+
+ iD.operations.addTemporary(this.map, this.falsenode);
+ // way.nodes = way.nodes.slice();
+ way.nodes.push(this.falsenode.id);
+
+ surface.on('mousemove.drawroad', function() {
+ var ll = this.map.projection.invert(d3.mouse(surface.node()));
+ this.falsenode.lon = ll[0];
+ this.falsenode.lat = ll[1];
+ this.map.update();
+ }.bind(this));
+
+ surface.on('click.drawroad', function() {
+ d3.event.stopPropagation();
+
+ way.nodes.pop();
+
+ var ll = this.map.projection.invert(d3.mouse(surface.node()));
+ var node = this.node(ll);
+
+ way.nodes.push(node.id);
+
+ iD.operations.changeWayNodes(this.map, way, node);
+
+ way.nodes = way.nodes.slice();
+ way.nodes.push(this.falsenode.id);
+ }.bind(this));
+
+ surface.on('dblclick.drawroad', function() {
+ d3.event.stopPropagation();
+ this.exit();
+ }.bind(this));
+ },
+ exit: function() {
+ iD.operations.addTemporary(this.map, this.falsenode);
+ this.map.surface.on('.drawroad', null);
+ d3.select(document).on('.drawroad', null);
+ d3.selectAll('#drawroad').remove();
+ }
+ };
+};
+
iD.actions.AddArea = {
- bind: function(controller, map) {
- this.controller = controller;
- this.map = map;
- d3.selectAll('button#area').on('click', function() {
- iD.actions.AddArea.enter();
- });
- },
enter: function() {
d3.selectAll('button').classed('active', false);
d3.selectAll('button#area').classed('active', true);
@@ -90,22 +178,19 @@ iD.actions.AddArea = {
};
iD.actions.Move = {
- bind: function(controller, map) {
- this.controller = controller;
- this.map = map;
- },
enter: function() {
d3.selectAll('button').classed('active', false);
},
exit: function() { }
};
+
iD.controller = function(map) {
var controller = { action: null };
- for (var a in iD.actions) iD.actions[a].bind(controller, map);
-
controller.go = function(x) {
+ x.controller = controller;
+ x.map = map;
if (controller.action) {
controller.action.exit();
}
diff --git a/js/iD/actions/operations.js b/js/iD/actions/operations.js
index e0f1bc73c..873fa6fe9 100644
--- a/js/iD/actions/operations.js
+++ b/js/iD/actions/operations.js
@@ -8,3 +8,39 @@ iD.operations.addNode = function(map, node) {
}, 'added a place');
map.update();
};
+
+iD.operations.startWay = function(map, way) {
+ map.graph.modify(function(graph) {
+ var o = {};
+ o[way.id] = way;
+ return graph.set(o);
+ }, 'started a road');
+ map.update();
+};
+
+iD.operations.changeWayNodes = function(map, way, node) {
+ map.graph.modify(function(graph) {
+ var o = {};
+ way.nodes = way.nodes.slice();
+ o[way.id] = pdata.object(way).get();
+ o[node.id] = node;
+ return graph.set(o);
+ }, 'added to a road');
+ map.update();
+};
+
+iD.operations.addTemporary = function(map, node) {
+ map.graph.modify(function(graph) {
+ var o = {};
+ o[node.id] = node;
+ return graph.set(o);
+ }, '');
+ map.update();
+};
+
+iD.operations.removeTemporary = function(map, node) {
+ map.graph.modify(function(graph) {
+ return graph.remove(node.id);
+ }, '');
+ map.update();
+};
diff --git a/js/iD/renderer/Map.js b/js/iD/renderer/Map.js
index ed1ed89ba..9bdc1a937 100755
--- a/js/iD/renderer/Map.js
+++ b/js/iD/renderer/Map.js
@@ -354,6 +354,8 @@ iD.Map = function(elem) {
map.undo = undo;
map.redo = redo;
+ map.redraw = redraw;
+
setSize(parent.node().offsetWidth, parent.node().offsetHeight);
redraw();