From 27861ca6b285e572b457f311e3db26c9dc557f69 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Thu, 7 Mar 2013 11:57:43 -0800 Subject: [PATCH] Implement multiselect cursors (fixes #296) --- css/map.css | 11 ++++++ js/id/behavior/select.js | 72 ++++++++++++++++++++++++++------------- test/spec/spec_helpers.js | 9 ++++- 3 files changed, 68 insertions(+), 24 deletions(-) diff --git a/css/map.css b/css/map.css index 3ae6ec183..a1ba8059d 100644 --- a/css/map.css +++ b/css/map.css @@ -798,6 +798,17 @@ text.point { cursor: url(../img/cursor-select-split.png), pointer; } +.mode-select .behavior-multiselect .point, +.mode-select .behavior-multiselect .vertex, +.mode-select .behavior-multiselect .line, +.mode-select .behavior-multiselect .area { + cursor: url(../img/cursor-select-add.png), pointer; +} + +.mode-select .behavior-multiselect .selected { + cursor: url(../img/cursor-select-remove.png), pointer; +} + .point:active, .vertex:active, .line:active, diff --git a/js/id/behavior/select.js b/js/id/behavior/select.js index 100cfcb78..1b3adb6fe 100644 --- a/js/id/behavior/select.js +++ b/js/id/behavior/select.js @@ -1,34 +1,60 @@ iD.behavior.Select = function(context) { - var behavior = function(selection) { - function click() { - var datum = d3.event.target.__data__; - if (!(datum instanceof iD.Entity)) { - if (!d3.event.shiftKey) - context.enter(iD.modes.Browse(context)); - - } else if (!d3.event.shiftKey) { - // Avoid re-entering Select mode with same entity. - if (context.selection().length !== 1 || context.selection()[0] !== datum.id) { - context.enter(iD.modes.Select(context, [datum.id])); - } else { - context.mode().reselect(); - } - } else if (context.selection().indexOf(datum.id) >= 0) { - var selection = _.without(context.selection(), datum.id); - context.enter(selection.length ? - iD.modes.Select(context, selection) : - iD.modes.Browse(context)); - - } else { - context.enter(iD.modes.Select(context, context.selection().concat([datum.id]))); - } + function keydown() { + if (d3.event && d3.event.shiftKey) { + context.surface() + .classed('behavior-multiselect', true); } + } + + function keyup() { + if (!d3.event || !d3.event.shiftKey) { + context.surface() + .classed('behavior-multiselect', false); + } + } + + function click() { + var datum = d3.event.target.__data__; + if (!(datum instanceof iD.Entity)) { + if (!d3.event.shiftKey) + context.enter(iD.modes.Browse(context)); + + } else if (!d3.event.shiftKey) { + // Avoid re-entering Select mode with same entity. + if (context.selection().length !== 1 || context.selection()[0] !== datum.id) { + context.enter(iD.modes.Select(context, [datum.id])); + } else { + context.mode().reselect(); + } + } else if (context.selection().indexOf(datum.id) >= 0) { + var selection = _.without(context.selection(), datum.id); + context.enter(selection.length ? + iD.modes.Select(context, selection) : + iD.modes.Browse(context)); + + } else { + context.enter(iD.modes.Select(context, context.selection().concat([datum.id]))); + } + } + + var behavior = function(selection) { + d3.select(window) + .on('keydown.select', keydown) + .on('keyup.select', keyup); selection.on('click.select', click); + + keydown(); }; behavior.off = function(selection) { + d3.select(window) + .on('keydown.select', null) + .on('keyup.select', null); + selection.on('click.select', null); + + keyup(); }; return behavior; diff --git a/test/spec/spec_helpers.js b/test/spec/spec_helpers.js index 7a62e76b9..1df2537e0 100644 --- a/test/spec/spec_helpers.js +++ b/test/spec/spec_helpers.js @@ -2,7 +2,14 @@ iD.debug = true; mocha.setup({ ui: 'bdd', - globals: ['__onresize.tail-size', '__onmousemove.zoom', '__onmouseup.zoom', '__onclick.draw'] + globals: [ + '__onresize.tail-size', + '__onmousemove.zoom', + '__onmouseup.zoom', + '__onkeydown.select', + '__onkeyup.select', + '__onclick.draw' + ] }); var expect = chai.expect;