diff --git a/index.html b/index.html
index cc45f4a48..387f4a0e1 100644
--- a/index.html
+++ b/index.html
@@ -104,11 +104,13 @@
+
+
diff --git a/js/id/modes/move_way.js b/js/id/modes/move_way.js
new file mode 100644
index 000000000..7fe07d1ce
--- /dev/null
+++ b/js/id/modes/move_way.js
@@ -0,0 +1,69 @@
+iD.modes.MoveWay = function(wayId) {
+ var mode = {
+ id: 'move-way'
+ };
+
+ 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;
+
+ var way = graph.entity(wayId),
+ origin = d3.mouse(selection.node());
+
+ history.perform(
+ iD.actions.Noop(),
+ 'moved a way');
+
+ function move() {
+ var p = d3.mouse(selection.node()),
+ delta = [p[0] - origin[0],
+ p[1] - origin[1]];
+
+ origin = p;
+
+ history.replace(
+ iD.actions.MoveWay(wayId, delta, projection),
+ 'moved a way');
+ }
+
+ function finish() {
+ d3.event.stopPropagation();
+ controller.enter(iD.modes.Select(way, true));
+ }
+
+ function cancel() {
+ history.pop();
+ controller.enter(iD.modes.Select(way, true));
+ }
+
+ selection
+ .on('mousemove.move-way', move)
+ .on('click.move-way', finish);
+
+ keybinding
+ .on('⎋', cancel)
+ .on('↩', finish);
+
+ d3.select(document)
+ .call(keybinding);
+ };
+
+ mode.exit = function() {
+ var map = mode.map,
+ selection = map.surface;
+
+ selection
+ .on('mousemove.move-way', null)
+ .on('click.move-way', null);
+
+ keybinding.off();
+ };
+
+ return mode;
+};
diff --git a/js/id/modes/select.js b/js/id/modes/select.js
index 8871dd2ec..06c05b7ea 100644
--- a/js/id/modes/select.js
+++ b/js/id/modes/select.js
@@ -43,7 +43,6 @@ iD.modes.Select = function(entity, initial) {
behaviors = [
iD.behavior.Hover(),
iD.behavior.DragNode(mode),
- iD.behavior.DragWay(mode),
iD.behavior.DragMidpoint(mode)];
behaviors.forEach(function(behavior) {
diff --git a/js/id/operations/move.js b/js/id/operations/move.js
new file mode 100644
index 000000000..9806ede67
--- /dev/null
+++ b/js/id/operations/move.js
@@ -0,0 +1,18 @@
+iD.operations.Move = function(entityId, mode) {
+ var operation = function() {
+ mode.controller.enter(iD.modes.MoveWay(entityId));
+ };
+
+ operation.available = function(graph) {
+ return graph.entity(entityId).type === 'way';
+ };
+
+ operation.enabled = function() {
+ return true;
+ };
+
+ operation.id = "move";
+ operation.title = "Move";
+
+ return operation;
+};
diff --git a/js/id/ui/radial_menu.js b/js/id/ui/radial_menu.js
index a891b7d8e..d38ef3679 100644
--- a/js/id/ui/radial_menu.js
+++ b/js/id/ui/radial_menu.js
@@ -8,6 +8,11 @@ iD.ui.RadialMenu = function(entity, mode) {
.map(function (o) { return o(entity.id, mode); })
.filter(function (o) { return o.available(graph); });
+ function click(operation) {
+ d3.event.stopPropagation();
+ operation(history);
+ }
+
var arc = d3.svg.arc()
.outerRadius(70)
.innerRadius(30)
@@ -28,7 +33,7 @@ iD.ui.RadialMenu = function(entity, mode) {
.attr('class', function (d) { return 'radial-menu-item radial-menu-item-' + d.id; })
.attr('d', arc)
.classed('disabled', function (d) { return !d.enabled(graph); })
- .on('click', function (d) { d(history); });
+ .on('click', click);
arcs.append('text')
.attr("transform", function(d, i) { return "translate(" + arc.centroid(d, i) + ")"; })
diff --git a/test/index.html b/test/index.html
index de83d89e0..00dc91ed5 100644
--- a/test/index.html
+++ b/test/index.html
@@ -98,11 +98,13 @@
+
+