diff --git a/index.html b/index.html
index 369d1f72a..0979fa558 100644
--- a/index.html
+++ b/index.html
@@ -91,6 +91,8 @@
+
+
diff --git a/js/id/behavior/draw.js b/js/id/behavior/draw.js
new file mode 100644
index 000000000..f09ed79e4
--- /dev/null
+++ b/js/id/behavior/draw.js
@@ -0,0 +1,54 @@
+iD.behavior.Draw = function () {
+ var event = d3.dispatch('move', 'add', 'drop', 'cancel', 'finish'),
+ keybinding = d3.keybinding('draw');
+
+ function draw(selection) {
+ function mousemove() {
+ event.move();
+ }
+
+ function click() {
+ event.add();
+ }
+
+ function backspace() {
+ d3.event.preventDefault();
+ event.drop();
+ }
+
+ function del() {
+ d3.event.preventDefault();
+ event.cancel();
+ }
+
+ function ret() {
+ d3.event.preventDefault();
+ event.finish();
+ }
+
+ selection
+ .on('mousemove.draw', mousemove)
+ .on('click.draw', click);
+
+ keybinding
+ .on('⌫', backspace)
+ .on('⌦', del)
+ .on('⎋', ret)
+ .on('↩', ret);
+
+ d3.select(document)
+ .call(keybinding);
+
+ return draw;
+ }
+
+ draw.off = function(selection) {
+ selection
+ .on('mousemove.draw', null)
+ .on('click.draw', null);
+
+ keybinding.off();
+ };
+
+ return d3.rebind(draw, event, 'on');
+};
diff --git a/js/id/behavior/draw_way.js b/js/id/behavior/draw_way.js
new file mode 100644
index 000000000..f4909b150
--- /dev/null
+++ b/js/id/behavior/draw_way.js
@@ -0,0 +1,146 @@
+iD.behavior.DrawWay = function(wayId, headId, tailId, index, mode) {
+ var map = mode.map,
+ history = mode.history,
+ controller = mode.controller,
+ event = d3.dispatch('add', 'addHead', 'addTail', 'addNode', 'addWay'),
+ way = mode.history.graph().entity(wayId),
+ nodeId = way.nodes[index],
+ hover, draw;
+
+ function move() {
+ history.replace(
+ iD.actions.MoveNode(nodeId, map.mouseCoordinates()),
+ history.undoAnnotation());
+ }
+
+ function add() {
+ var datum = d3.select(d3.event.target).datum() || {};
+
+ if (datum.id === headId) {
+ event.addHead(datum);
+ } else if (datum.id === tailId) {
+ event.addTail(datum);
+ } else if (datum.type === 'node' && datum.id !== nodeId) {
+ event.addNode(datum);
+ } else if (datum.type === 'way') {
+ var choice = iD.geo.chooseIndex(datum, d3.mouse(map.surface.node()), map);
+ event.addWay(datum, choice.loc, choice.index);
+ } else if (datum.midpoint) {
+ var way = history.graph().entity(datum.way);
+ event.addWay(way, datum.loc, datum.index);
+ } else {
+ event.add(map.mouseCoordinates());
+ }
+ }
+
+ function undone() {
+ var way = history.graph().entity(wayId);
+ if (way) {
+ controller.enter(mode);
+ } else {
+ controller.enter(iD.modes.Browse());
+ }
+ }
+
+ var drawWay = function(surface) {
+ map.fastEnable(false)
+ .minzoom(16)
+ .dblclickEnable(false);
+
+ surface.call(hover)
+ .call(draw)
+ .selectAll('.way, .node')
+ .filter(function (d) { return d.id === wayId || d.id === nodeId; })
+ .classed('active', true);
+
+ history.on('undone.draw', undone);
+ };
+
+ drawWay.off = function(surface) {
+ map.fastEnable(true)
+ .minzoom(0)
+ .tail(false);
+
+ window.setTimeout(function() {
+ map.dblclickEnable(true);
+ }, 1000);
+
+ surface.call(hover.off)
+ .call(draw.off)
+ .selectAll('.way, .node')
+ .classed('active', false);
+
+ history.on('undone.draw', null);
+ };
+
+ // Connect the way to an existing node. Continue drawing, or enter the optional `newMode`.
+ drawWay.addNode = function(node, annotation, newMode) {
+ history.perform(
+ iD.actions.AddWayNode(wayId, node.id, index),
+ annotation);
+
+ controller.enter(newMode || mode);
+ };
+
+ // Connect the way to an existing way.
+ drawWay.addWay = function(way, loc, wayIndex, annotation) {
+ var newNode = iD.Node({loc: loc});
+
+ history.perform(
+ iD.actions.AddNode(newNode),
+ iD.actions.AddWayNode(wayId, newNode.id, index),
+ iD.actions.AddWayNode(way.id, newNode.id, wayIndex),
+ annotation);
+
+ controller.enter(mode);
+ };
+
+ // Accept the current position of the temporary node and continue drawing.
+ drawWay.add = function(loc, annotation) {
+ var newNode = iD.Node({loc: loc});
+
+ history.perform(
+ iD.actions.AddNode(newNode),
+ iD.actions.AddWayNode(wayId, newNode.id, index),
+ annotation);
+
+ controller.enter(mode);
+ };
+
+ // Remove the temporary node and the last connected node but continue drawing.
+ drawWay.drop = function() {
+ history.undo();
+ };
+
+ // 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.replace(
+ iD.actions.DeleteNode(nodeId),
+ history.undoAnnotation());
+
+ var way = history.graph().entity(wayId);
+ if (way) {
+ controller.enter(iD.modes.Select(way, true));
+ } else {
+ controller.enter(iD.modes.Browse());
+ }
+ };
+
+ // Cancel the draw operation and return to browse, deleting everything drawn.
+ drawWay.cancel = function() {
+ history.perform(iD.actions.DeleteWay(wayId), 'cancelled drawing');
+ controller.enter(iD.modes.Browse());
+ };
+
+ hover = iD.behavior.Hover();
+
+ draw = iD.behavior.Draw()
+ .on('move', move)
+ .on('add', add)
+ .on('drop', drawWay.drop)
+ .on('cancel', drawWay.cancel)
+ .on('finish', drawWay.finish);
+
+ return d3.rebind(drawWay, event, 'on');
+};
diff --git a/js/id/graph/history.js b/js/id/graph/history.js
index 142a9eeca..a1865715e 100644
--- a/js/id/graph/history.js
+++ b/js/id/graph/history.js
@@ -8,7 +8,7 @@ iD.History = function() {
var annotation;
- if (_.isString(_.last(actions))) {
+ if (!_.isFunction(_.last(actions))) {
annotation = actions.pop();
}
diff --git a/js/id/modes/add_area.js b/js/id/modes/add_area.js
index d3936229e..58109befc 100644
--- a/js/id/modes/add_area.js
+++ b/js/id/modes/add_area.js
@@ -6,30 +6,33 @@ iD.modes.AddArea = function() {
description: 'Add parks, buildings, lakes, or other areas to the map.'
};
- var keybinding = d3.keybinding('add-area');
+ var behavior;
mode.enter = function() {
var map = mode.map,
+ surface = map.surface,
history = mode.history,
controller = mode.controller;
map.dblclickEnable(false)
.tail('Click on the map to start drawing an area, like a park, lake, or building.');
- map.surface.on('click.addarea', function() {
+ function add() {
var datum = d3.select(d3.event.target).datum() || {},
- way = iD.Way({tags: { area: 'yes' }});
+ way = iD.Way({tags: { area: 'yes' }}),
+ node;
if (datum.type === 'node') {
// start from an existing node
+ node = datum;
history.perform(
iD.actions.AddWay(way),
- iD.actions.AddWayNode(way.id, datum.id),
- iD.actions.AddWayNode(way.id, datum.id));
+ iD.actions.AddWayNode(way.id, node.id),
+ iD.actions.AddWayNode(way.id, node.id));
} else {
// start from a new node
- var node = iD.Node({loc: map.mouseCoordinates()});
+ node = iD.Node({loc: map.mouseCoordinates()});
history.perform(
iD.actions.AddWay(way),
iD.actions.AddNode(node),
@@ -37,24 +40,36 @@ iD.modes.AddArea = function() {
iD.actions.AddWayNode(way.id, node.id));
}
+ node = iD.Node({loc: node.loc});
+
+ history.replace(
+ iD.actions.AddNode(node),
+ iD.actions.AddWayNode(way.id, node.id, -1),
+ 'started an area');
+
controller.enter(iD.modes.DrawArea(way.id));
- });
+ }
- keybinding.on('⎋', function() {
+ function cancel() {
controller.exit();
- });
+ }
- d3.select(document)
- .call(keybinding);
+ behavior = iD.behavior.Draw()
+ .on('add', add)
+ .on('cancel', cancel)
+ .on('finish', cancel)
+ (surface);
};
mode.exit = function() {
+ var map = mode.map,
+ surface = map.surface;
+
window.setTimeout(function() {
- mode.map.dblclickEnable(true);
+ map.dblclickEnable(true);
}, 1000);
- mode.map.tail(false);
- mode.map.surface.on('click.addarea', null);
- keybinding.off();
+ map.tail(false);
+ behavior.off(surface);
};
return mode;
diff --git a/js/id/modes/add_line.js b/js/id/modes/add_line.js
index 190bf7e16..6b3a747e1 100644
--- a/js/id/modes/add_line.js
+++ b/js/id/modes/add_line.js
@@ -6,37 +6,38 @@ iD.modes.AddLine = function() {
description: 'Lines can be highways, streets, pedestrian paths, or even canals.'
};
- var keybinding = d3.keybinding('add-line');
+ var behavior;
mode.enter = function() {
var map = mode.map,
+ surface = map.surface,
graph = map.history().graph(),
- node,
history = mode.history,
controller = mode.controller;
map.dblclickEnable(false)
.tail('Click on the map to start drawing an road, path, or route.');
- map.surface.on('click.addline', function() {
+ function add() {
var datum = d3.select(d3.event.target).datum() || {},
way = iD.Way({ tags: { highway: 'residential' } }),
- direction = 'forward';
+ direction = 'forward',
+ node;
if (datum.type === 'node') {
// continue an existing way
- var id = datum.id;
- var parents = history.graph(graph).parentWays(datum);
+ node = datum;
+ var parents = history.graph(graph).parentWays(node);
var isLine = parents.length && parents[0].geometry(graph) === 'line';
- if (isLine && parents[0].nodes[0] === id ) {
+ if (isLine && parents[0].first() === node.id) {
way = parents[0];
direction = 'backward';
- } else if (isLine && _.last(parents[0].nodes) === id) {
+ } else if (isLine && parents[0].last() === node.id) {
way = parents[0];
} else {
history.perform(
iD.actions.AddWay(way),
- iD.actions.AddWayNode(way.id, datum.id));
+ iD.actions.AddWayNode(way.id, node.id));
}
} else if (datum.type === 'way') {
@@ -60,22 +61,36 @@ iD.modes.AddLine = function() {
iD.actions.AddWayNode(way.id, node.id));
}
- controller.enter(iD.modes.DrawLine(way.id, direction));
- });
+ var index = (direction === 'forward') ? way.nodes.length : 0,
- keybinding.on('⎋', function() {
+ node = iD.Node({loc: node.loc});
+
+ history.replace(
+ iD.actions.AddNode(node),
+ iD.actions.AddWayNode(way.id, node.id, index),
+ 'started a line');
+
+ controller.enter(iD.modes.DrawLine(way.id, direction, node));
+ }
+
+ function cancel() {
controller.exit();
- });
+ }
- d3.select(document)
- .call(keybinding);
+ behavior = iD.behavior.Draw()
+ .on('add', add)
+ .on('cancel', cancel)
+ .on('finish', cancel)
+ (surface);
};
mode.exit = function() {
- mode.map.dblclickEnable(true);
- mode.map.tail(false);
- mode.map.surface.on('click.addline', null);
- keybinding.off();
+ var map = mode.map,
+ surface = map.surface;
+
+ map.dblclickEnable(true);
+ map.tail(false);
+ behavior.off(surface);
};
return mode;
diff --git a/js/id/modes/add_point.js b/js/id/modes/add_point.js
index bacdc1541..40c8e84ad 100644
--- a/js/id/modes/add_point.js
+++ b/js/id/modes/add_point.js
@@ -5,16 +5,17 @@ iD.modes.AddPoint = function() {
description: 'Restaurants, monuments, and postal boxes are points.'
};
- var keybinding = d3.keybinding('add-point');
+ var behavior;
mode.enter = function() {
var map = mode.map,
+ surface = map.surface,
history = mode.history,
controller = mode.controller;
map.tail('Click on the map to add a point.');
- map.surface.on('click.addpoint', function() {
+ function add() {
var node = iD.Node({loc: map.mouseCoordinates()});
history.perform(
@@ -22,20 +23,25 @@ iD.modes.AddPoint = function() {
'added a point');
controller.enter(iD.modes.Select(node, true));
- });
+ }
- keybinding.on('⎋', function() {
+ function cancel() {
controller.exit();
- });
+ }
- d3.select(document)
- .call(keybinding);
+ behavior = iD.behavior.Draw()
+ .on('add', add)
+ .on('cancel', cancel)
+ .on('finish', cancel)
+ (surface);
};
mode.exit = function() {
- mode.map.tail(false);
- mode.map.surface.on('click.addpoint', null);
- keybinding.off();
+ var map = mode.map,
+ surface = map.surface;
+
+ map.tail(false);
+ behavior.off(surface);
};
return mode;
diff --git a/js/id/modes/draw_area.js b/js/id/modes/draw_area.js
index 2c779538d..d692ae550 100644
--- a/js/id/modes/draw_area.js
+++ b/js/id/modes/draw_area.js
@@ -4,147 +4,39 @@ iD.modes.DrawArea = function(wayId) {
id: 'draw-area'
};
- var keybinding = d3.keybinding('draw-area');
+ var behavior;
mode.enter = function() {
- var map = mode.map,
- surface = map.surface,
- history = mode.history,
- controller = mode.controller,
- way = history.graph().entity(wayId),
- index = way.nodes.length - 1,
+ var way = mode.history.graph().entity(wayId),
+ index = way.nodes.length - 2,
headId = way.nodes[index - 1],
- tailId = way.first(),
- node = iD.Node({loc: map.mouseCoordinates()});
+ tailId = way.first();
- map.dblclickEnable(false)
- .fastEnable(false);
- map.tail('Click to add points to your area. Click the first point to finish the area.');
-
- history.perform(
- iD.actions.AddNode(node),
- iD.actions.AddWayNode(way.id, node.id, index));
-
- surface.selectAll('.way, .node')
- .filter(function (d) { return d.id === wayId || d.id === node.id; })
- .classed('active', true);
-
- function ReplaceTemporaryNode(replacementId) {
- return function(graph) {
- graph = graph.replace(graph.entity(wayId).updateNode(replacementId, index));
- graph = graph.remove(node);
- return graph;
- }
+ function addHeadTail() {
+ behavior.finish();
}
- function mousemove() {
- history.replace(iD.actions.MoveNode(node.id, map.mouseCoordinates()));
+ function addNode(node) {
+ behavior.addNode(node, way.nodes.length > 2 ? 'added to an area' : '');
}
- function click() {
- var datum = d3.select(d3.event.target).datum() || {};
-
- if (datum.id === tailId || datum.id === headId) {
- if (way.nodes.length > 3) {
- history.undo();
- controller.enter(iD.modes.Select(way, true));
- } else {
- // Areas with less than 3 nodes gets deleted
- history.replace(iD.actions.DeleteWay(way.id));
- controller.enter(iD.modes.Browse());
- }
-
- } else if (datum.type === 'node' && datum.id !== node.id) {
- // connect the way to an existing node
- history.replace(
- ReplaceTemporaryNode(datum.id),
- way.nodes.length > 2 ? 'added to an area' : '');
-
- controller.enter(iD.modes.DrawArea(wayId));
-
- } else {
- history.replace(
- iD.actions.Noop(),
- way.nodes.length > 2 ? 'added to an area' : '');
-
- controller.enter(iD.modes.DrawArea(wayId));
- }
+ function add(loc) {
+ behavior.add(loc, way.nodes.length > 2 ? 'added to an area' : '');
}
- function backspace() {
- d3.event.preventDefault();
+ behavior = iD.behavior.DrawWay(wayId, headId, tailId, index, mode)
+ .on('addHead', addHeadTail)
+ .on('addTail', addHeadTail)
+ .on('addNode', addNode)
+ .on('addWay', add)
+ .on('add', add);
- history.replace(
- iD.actions.DeleteNode(node.id),
- iD.actions.DeleteNode(headId));
-
- if (history.graph().entity(wayId)) {
- controller.enter(iD.modes.DrawArea(wayId));
- } else {
- // The way was deleted because it had too few nodes.
- controller.enter(iD.modes.Browse());
- }
- }
-
- function del() {
- d3.event.preventDefault();
- history.replace(iD.actions.DeleteWay(wayId));
- controller.enter(iD.modes.Browse());
- }
-
- function ret() {
- d3.event.preventDefault();
-
- history.replace(iD.actions.DeleteNode(node.id));
-
- if (history.graph().entity(wayId)) {
- controller.enter(iD.modes.Select(way, true));
- } else {
- // The way was deleted because it had too few nodes.
- controller.enter(iD.modes.Browse());
- }
- }
-
- surface
- .on('mousemove.drawarea', mousemove)
- .on('click.drawarea', click);
-
- keybinding
- .on('⌫', backspace)
- .on('⌦', del)
- .on('⎋', ret)
- .on('↩', ret);
-
- d3.select(document)
- .call(keybinding);
-
- history.on('undone.drawarea', function () {
- controller.enter(iD.modes.Browse());
- });
+ mode.map.surface.call(behavior);
+ mode.map.tail('Click to add points to your area. Click the first point to finish the area.');
};
mode.exit = function() {
- var map = mode.map,
- surface = map.surface,
- history = mode.history;
-
- surface.selectAll('.way, .node')
- .classed('active', false);
-
- map.tail(false);
- map.fastEnable(true);
-
- surface
- .on('mousemove.drawarea', null)
- .on('click.drawarea', null);
-
- keybinding.off();
-
- history.on('undone.drawarea', null);
-
- window.setTimeout(function() {
- mode.map.dblclickEnable(true);
- }, 1000);
+ mode.map.surface.call(behavior.off);
};
return mode;
diff --git a/js/id/modes/draw_line.js b/js/id/modes/draw_line.js
index b8fabeca5..1e09ab0ac 100644
--- a/js/id/modes/draw_line.js
+++ b/js/id/modes/draw_line.js
@@ -4,182 +4,54 @@ iD.modes.DrawLine = function(wayId, direction) {
id: 'draw-line'
};
- var keybinding = d3.keybinding('draw-line');
+ var behavior;
mode.enter = function() {
- var map = mode.map,
- surface = map.surface,
- history = mode.history,
- controller = mode.controller,
- way = history.graph().entity(wayId),
- node = iD.Node({loc: map.mouseCoordinates()}),
- index = (direction === 'forward') ? way.nodes.length : 0,
- headId = (direction === 'forward') ? way.last() : way.first(),
+ var way = mode.history.graph().entity(wayId),
+ index = (direction === 'forward') ? way.nodes.length - 1 : 0,
+ headId = (direction === 'forward') ? way.nodes[index - 1] : way.nodes[index + 1],
tailId = (direction === 'forward') ? way.first() : way.last();
- iD.behavior.Hover()(surface);
+ function addHead() {
+ behavior.finish();
+ }
- map.dblclickEnable(false)
- .fastEnable(false)
- .tail('Click to add more points to the line. ' +
+ function addTail(node) {
+ // connect the way in a loop
+ if (way.nodes.length > 2) {
+ behavior.addNode(node, 'added to a line', iD.modes.Select(way, true))
+ } else {
+ behavior.cancel();
+ }
+ }
+
+ function addNode(node) {
+ behavior.addNode(node, 'added to a line');
+ }
+
+ function addWay(way, loc, index) {
+ behavior.addWay(way, loc, index, 'added to a line');
+ }
+
+ function add(loc) {
+ behavior.add(loc, 'added to a line');
+ }
+
+ behavior = iD.behavior.DrawWay(wayId, headId, tailId, index, mode)
+ .on('addHead', addHead)
+ .on('addTail', addTail)
+ .on('addNode', addNode)
+ .on('addWay', addWay)
+ .on('add', add);
+
+ mode.map.surface.call(behavior);
+ mode.map.tail('Click to add more points to the line. ' +
'Click on other lines to connect to them, and double-click to ' +
'end the line.');
-
- map.minzoom(16);
-
- history.perform(
- iD.actions.AddNode(node),
- iD.actions.AddWayNode(wayId, node.id, index));
-
- surface.selectAll('.way, .node')
- .filter(function (d) { return d.id === wayId || d.id === node.id; })
- .classed('active', true);
-
- function ReplaceTemporaryNode(replacementId) {
- return function(graph) {
- graph = graph.replace(graph.entity(wayId).updateNode(replacementId, index));
- graph = graph.remove(node);
- return graph;
- }
- }
-
- function mousemove() {
- history.replace(iD.actions.MoveNode(node.id, map.mouseCoordinates()));
- }
-
- function click() {
- var datum = d3.select(d3.event.target).datum() || {};
-
- if (datum.id === tailId) {
- // connect the way in a loop
- if (way.nodes.length > 2) {
- history.replace(
- ReplaceTemporaryNode(tailId),
- 'added to a line');
-
- controller.enter(iD.modes.Select(way, true));
-
- } else {
- history.replace(iD.actions.DeleteWay(way.id));
- controller.enter(iD.modes.Browse());
- }
-
- } else if (datum.id === headId) {
- // finish the way
- history.undo();
-
- controller.enter(iD.modes.Select(way, true));
-
- } else if (datum.type === 'node' && datum.id !== node.id) {
- // connect the way to an existing node
- history.replace(
- ReplaceTemporaryNode(datum.id),
- 'added to a line');
-
- controller.enter(iD.modes.DrawLine(wayId, direction));
-
- } else if (datum.type === 'way' || datum.midpoint) {
- var choice;
- // connect the way to an existing way
- if (datum.midpoint) {
- // if clicked on midpoint
- datum.id = datum.way;
- choice = datum;
- } else {
- choice = iD.geo.chooseIndex(datum, d3.mouse(surface.node()), map);
- }
-
- history.replace(
- iD.actions.MoveNode(node.id, choice.loc),
- iD.actions.AddWayNode(datum.id, node.id, choice.index),
- 'added to a line');
-
- controller.enter(iD.modes.DrawLine(wayId, direction));
-
- } else {
- history.replace(
- iD.actions.Noop(),
- 'added to a line');
-
- controller.enter(iD.modes.DrawLine(wayId, direction));
- }
- }
-
- function backspace() {
- d3.event.preventDefault();
-
- history.replace(
- iD.actions.DeleteNode(node.id),
- iD.actions.DeleteNode(headId));
-
- if (history.graph().entity(wayId)) {
- controller.enter(iD.modes.DrawLine(wayId, direction));
- } else {
- // The way was deleted because it had too few nodes.
- controller.enter(iD.modes.Browse());
- }
- }
-
- function del() {
- d3.event.preventDefault();
- history.replace(iD.actions.DeleteWay(wayId));
- controller.enter(iD.modes.Browse());
- }
-
- function ret() {
- d3.event.preventDefault();
-
- history.replace(iD.actions.DeleteNode(node.id));
-
- if (history.graph().entity(wayId)) {
- controller.enter(iD.modes.Select(way, true));
- } else {
- // The way was deleted because it had too few nodes.
- controller.enter(iD.modes.Browse());
- }
- }
-
- surface
- .on('mousemove.drawline', mousemove)
- .on('click.drawline', click);
-
- keybinding
- .on('⌫', backspace)
- .on('⌦', del)
- .on('⎋', ret)
- .on('↩', ret);
-
- d3.select(document)
- .call(keybinding);
-
- history.on('undone.drawline', function () {
- controller.enter(iD.modes.Browse());
- });
};
mode.exit = function() {
- var map = mode.map,
- surface = map.surface,
- history = mode.history;
-
- surface.selectAll('.way, .node')
- .classed('active', false);
-
- map.tail(false);
- map.fastEnable(true);
- map.minzoom(0);
-
- surface
- .on('mousemove.drawline', null)
- .on('click.drawline', null);
-
- keybinding.off();
-
- history.on('undone.drawline', null);
-
- window.setTimeout(function() {
- mode.map.dblclickEnable(true);
- }, 1000);
+ mode.map.surface.call(behavior.off);
};
return mode;
diff --git a/js/id/renderer/map.js b/js/id/renderer/map.js
index 7cf07790d..fff0deac7 100644
--- a/js/id/renderer/map.js
+++ b/js/id/renderer/map.js
@@ -341,6 +341,7 @@ iD.Map = function() {
map.minzoom = function(_) {
if (!arguments.length) return minzoom;
minzoom = _;
+ return map;
};
map.history = function (_) {
diff --git a/test/index.html b/test/index.html
index 8e88c500b..10bba28ea 100644
--- a/test/index.html
+++ b/test/index.html
@@ -86,6 +86,8 @@
+
+