diff --git a/src/traces/bar/index.js b/src/traces/bar/index.js index f890fe8b673..823bca3059b 100644 --- a/src/traces/bar/index.js +++ b/src/traces/bar/index.js @@ -22,6 +22,7 @@ Bar.arraysToCalcdata = require('./arrays_to_calcdata'); Bar.plot = require('./plot'); Bar.style = require('./style'); Bar.hoverPoints = require('./hover'); +Bar.selectPoints = require('./select'); Bar.moduleType = 'trace'; Bar.name = 'bar'; diff --git a/src/traces/bar/plot.js b/src/traces/bar/plot.js index fdd5bfd33c2..2e37ef7292a 100644 --- a/src/traces/bar/plot.js +++ b/src/traces/bar/plot.js @@ -45,12 +45,13 @@ module.exports = function plot(gd, plotinfo, cdbar) { bartraces.append('g') .attr('class', 'points') .each(function(d) { - var t = d[0].t, - trace = d[0].trace, - poffset = t.poffset, - poffsetIsArray = Array.isArray(poffset); + var sel = d[0].node3 = d3.select(this); + var t = d[0].t; + var trace = d[0].trace; + var poffset = t.poffset; + var poffsetIsArray = Array.isArray(poffset); - d3.select(this).selectAll('g.point') + sel.selectAll('g.point') .data(Lib.identity) .enter().append('g').classed('point', true) .each(function(di, i) { @@ -69,12 +70,18 @@ module.exports = function plot(gd, plotinfo, cdbar) { y1 = ya.c2p(p1, true); x0 = xa.c2p(s0, true); x1 = xa.c2p(s1, true); + + // for selections + di.ct = [x1, (y0 + y1) / 2]; } else { x0 = xa.c2p(p0, true); x1 = xa.c2p(p1, true); y0 = ya.c2p(s0, true); y1 = ya.c2p(s1, true); + + // for selections + di.ct = [(x0 + x1) / 2, y1]; } if(!isNumeric(x0) || !isNumeric(x1) || diff --git a/src/traces/bar/select.js b/src/traces/bar/select.js new file mode 100644 index 00000000000..6e54c4de60d --- /dev/null +++ b/src/traces/bar/select.js @@ -0,0 +1,52 @@ +/** +* Copyright 2012-2017, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var DESELECTDIM = require('../../constants/interactions').DESELECTDIM; + +module.exports = function selectPoints(searchInfo, polygon) { + var cd = searchInfo.cd; + var selection = []; + var trace = cd[0].trace; + var node3 = cd[0].node3; + var i; + + if(trace.visible !== true) return; + + if(polygon === false) { + // clear selection + for(i = 0; i < cd.length; i++) { + cd[i].dim = 0; + } + } else { + for(i = 0; i < cd.length; i++) { + var di = cd[i]; + + if(polygon.contains(di.ct)) { + selection.push({ + pointNumber: i, + x: di.x, + y: di.y + }); + di.dim = 0; + } else { + di.dim = 1; + } + } + } + + node3.selectAll('.point').style('opacity', function(d) { + return d.dim ? DESELECTDIM : 1; + }); + node3.selectAll('text').style('opacity', function(d) { + return d.dim ? DESELECTDIM : 1; + }); + + return selection; +}; diff --git a/src/traces/histogram/index.js b/src/traces/histogram/index.js index bf743152181..d0cfeae5d63 100644 --- a/src/traces/histogram/index.js +++ b/src/traces/histogram/index.js @@ -35,6 +35,7 @@ Histogram.plot = require('../bar/plot'); Histogram.style = require('../bar/style'); Histogram.colorbar = require('../scatter/colorbar'); Histogram.hoverPoints = require('../bar/hover'); +Histogram.selectPoints = require('../bar/select'); Histogram.moduleType = 'trace'; Histogram.name = 'histogram'; diff --git a/test/jasmine/tests/select_test.js b/test/jasmine/tests/select_test.js index 67f6f8b2df0..00301826243 100644 --- a/test/jasmine/tests/select_test.js +++ b/test/jasmine/tests/select_test.js @@ -414,8 +414,13 @@ describe('Test select box and lasso per trace:', function() { pts.forEach(function(p, i) { var e = expected[i] || []; keys.forEach(function(k, j) { - expect(p[k]) - .toBe(e[j], msg + 'selected pt ' + i + ' - ' + k + ' val'); + var msgFull = msg + 'selected pt ' + i + ' - ' + k + ' val'; + + if(typeof e[j] === 'number') { + expect(p[k]).toBeCloseTo(e[j], 1, msgFull); + } else { + expect(p[k]).toBe(e[j], msgFull); + } }); }); @@ -428,11 +433,18 @@ describe('Test select box and lasso per trace:', function() { var callNumber = 0; return function(expected) { - var msg = '(call #' + callNumber + ') '; - var ranges = (selectedData.range || {})[subplot] || []; - - expect(ranges) - .toBeCloseTo2DArray(expected, tol, msg + 'select box range for ' + subplot); + var msg = '(call #' + callNumber + ') select box range '; + var ranges = selectedData.range || {}; + + if(subplot) { + expect(ranges[subplot] || []) + .toBeCloseTo2DArray(expected, tol, msg + 'for ' + subplot); + } else { + expect(ranges.x || []) + .toBeCloseToArray(expected[0], tol, msg + 'x coords'); + expect(ranges.y || []) + .toBeCloseToArray(expected[1], tol, msg + 'y coords'); + } callNumber++; }; @@ -443,11 +455,18 @@ describe('Test select box and lasso per trace:', function() { var callNumber = 0; return function(expected) { - var msg = '(call #' + callNumber + ') '; - var lassoPoints = (selectedData.lassoPoints || {})[subplot] || []; - - expect(lassoPoints) - .toBeCloseTo2DArray(expected, tol, msg + 'lasso points for ' + subplot); + var msg = '(call #' + callNumber + ') lasso points '; + var lassoPoints = selectedData.lassoPoints || {}; + + if(subplot) { + expect(lassoPoints[subplot] || []) + .toBeCloseTo2DArray(expected, tol, msg + 'for ' + subplot); + } else { + expect(lassoPoints.x || []) + .toBeCloseToArray(expected[0], tol, msg + 'x coords'); + expect(lassoPoints.y || []) + .toBeCloseToArray(expected[1], tol, msg + 'y coords'); + } callNumber++; }; @@ -708,4 +727,100 @@ describe('Test select box and lasso per trace:', function() { .catch(fail) .then(done); }, LONG_TIMEOUT_INTERVAL); + + it('should work for bar traces', function(done) { + var assertPoints = makeAssertPoints(['curveNumber', 'x', 'y']); + var assertRanges = makeAssertRanges(); + var assertLassoPoints = makeAssertLassoPoints(); + + var fig = Lib.extendDeep({}, require('@mocks/0')); + fig.layout.dragmode = 'lasso'; + + Plotly.plot(gd, fig) + .then(function() { + return _run( + [[350, 200], [400, 200], [400, 250], [350, 250], [350, 200]], + function() { + assertPoints([ + [0, 4.9, 0.371], [0, 5, 0.368], [0, 5.1, 0.356], [0, 5.2, 0.336], + [0, 5.3, 0.309], [0, 5.4, 0.275], [0, 5.5, 0.235], [0, 5.6, 0.192], + [0, 5.7, 0.145], + [1, 5.1, 0.485], [1, 5.2, 0.409], [1, 5.3, 0.327], + [1, 5.4, 0.24], [1, 5.5, 0.149], [1, 5.6, 0.059], + [2, 4.9, 0.473], [2, 5, 0.368], [2, 5.1, 0.258], + [2, 5.2, 0.146], [2, 5.3, 0.036] + ]); + assertLassoPoints([ + [4.87, 5.74, 5.74, 4.87, 4.87], + [0.53, 0.53, -0.02, -0.02, 0.53] + ]); + }, + null, LASSOEVENTS, 'bar lasso' + ); + }) + .then(function() { + return Plotly.relayout(gd, 'dragmode', 'select'); + }) + .then(function() { + return _run( + [[350, 200], [370, 220]], + function() { + assertPoints([ + [0, 4.9, 0.371], [0, 5, 0.368], [0, 5.1, 0.356], [0, 5.2, 0.336], + [1, 5.1, 0.485], [1, 5.2, 0.41], + [2, 4.9, 0.473], [2, 5, 0.37] + ]); + assertRanges([[4.87, 5.22], [0.31, 0.53]]); + }, + null, BOXEVENTS, 'bar select' + ); + }) + .catch(fail) + .then(done); + }); + + it('should work for histogram traces', function(done) { + var assertPoints = makeAssertPoints(['curveNumber', 'x', 'y']); + var assertRanges = makeAssertRanges(); + var assertLassoPoints = makeAssertLassoPoints(); + + var fig = Lib.extendDeep({}, require('@mocks/hist_grouped')); + fig.layout.dragmode = 'lasso'; + fig.layout.width = 600; + fig.layout.height = 500; + + Plotly.plot(gd, fig) + .then(function() { + return _run( + [[200, 200], [400, 200], [400, 350], [200, 350], [200, 200]], + function() { + assertPoints([ + [0, 1.8, 2], [1, 2.2, 1], [1, 3.2, 1] + ]); + assertLassoPoints([ + [1.66, 3.59, 3.59, 1.66, 1.66], + [2.17, 2.17, 0.69, 0.69, 2.17] + ]); + }, + null, LASSOEVENTS, 'histogram lasso' + ); + }) + .then(function() { + return Plotly.relayout(gd, 'dragmode', 'select'); + }) + .then(function() { + return _run( + [[200, 200], [400, 350]], + function() { + assertPoints([ + [0, 1.8, 2], [1, 2.2, 1], [1, 3.2, 1] + ]); + assertRanges([[1.66, 3.59], [0.69, 2.17]]); + }, + null, BOXEVENTS, 'bar select' + ); + }) + .catch(fail) + .then(done); + }); });