diff --git a/js/id/behavior/select.js b/js/id/behavior/select.js
index e078fdbf1..b5276a4d0 100644
--- a/js/id/behavior/select.js
+++ b/js/id/behavior/select.js
@@ -2,8 +2,12 @@ iD.behavior.Select = function(context) {
function click() {
var datum = d3.select(d3.event.target).datum();
if (datum instanceof iD.Entity) {
- context.enter(iD.modes.Select(context, [datum.id]));
- } else {
+ if (d3.event.shiftKey) {
+ context.enter(iD.modes.Select(context, context.selection().concat([datum.id])));
+ } else {
+ context.enter(iD.modes.Select(context, [datum.id]));
+ }
+ } else if (!d3.event.shiftKey) {
context.enter(iD.modes.Browse(context));
}
}
diff --git a/js/id/id.js b/js/id/id.js
index 0b2bbd617..358610525 100644
--- a/js/id/id.js
+++ b/js/id/id.js
@@ -56,6 +56,14 @@ window.iD = function () {
return mode;
};
+ context.selection = function() {
+ if (mode.id === 'select') {
+ return mode.selection();
+ } else {
+ return [];
+ }
+ };
+
/* Behaviors */
context.install = function(behavior) {
context.surface().call(behavior);
diff --git a/test/index.html b/test/index.html
index d32331ba9..16f86b781 100644
--- a/test/index.html
+++ b/test/index.html
@@ -185,6 +185,7 @@
+
diff --git a/test/index_packaged.html b/test/index_packaged.html
index 11f8368f4..588c8e0a3 100644
--- a/test/index_packaged.html
+++ b/test/index_packaged.html
@@ -80,6 +80,7 @@
+
diff --git a/test/spec/behavior/select.js b/test/spec/behavior/select.js
new file mode 100644
index 000000000..42c568cca
--- /dev/null
+++ b/test/spec/behavior/select.js
@@ -0,0 +1,54 @@
+describe("iD.behavior.Select", function() {
+ var a, b, context, behavior, container;
+
+ beforeEach(function() {
+ container = d3.select('body').append('div');
+
+ context = iD().container(container);
+
+ a = iD.Node({loc: [0, 0]});
+ b = iD.Node({loc: [0, 0]});
+
+ context.perform(iD.actions.AddEntity(a), iD.actions.AddEntity(b));
+
+ container.call(context.map())
+ .append('div')
+ .attr('class', 'inspector-wrap');
+
+ context.surface().selectAll('circle')
+ .data([a, b])
+ .enter().append('circle')
+ .attr('class', function(d) { return d.id; });
+
+ behavior = iD.behavior.Select(context);
+ context.install(behavior);
+ });
+
+ afterEach(function() {
+ context.uninstall(behavior);
+ container.remove();
+ });
+
+ specify("click on entity selects the entity", function() {
+ happen.click(context.surface().select('.' + a.id).node());
+ expect(context.selection()).to.eql([a.id]);
+ });
+
+ specify("click on empty space clears the selection", function() {
+ context.enter(iD.modes.Select(context, [a.id]));
+ happen.click(context.surface().node());
+ expect(context.selection()).to.eql([]);
+ });
+
+ specify("shift-click on entity adds the entity to the selection", function() {
+ context.enter(iD.modes.Select(context, [a.id]));
+ happen.click(context.surface().select('.' + b.id).node(), {shiftKey: true});
+ expect(context.selection()).to.eql([a.id, b.id]);
+ });
+
+ specify("shift-click on empty space leaves the selection unchanged", function() {
+ context.enter(iD.modes.Select(context, [a.id]));
+ happen.click(context.surface().node(), {shiftKey: true});
+ expect(context.selection()).to.eql([a.id]);
+ });
+});