diff --git a/src/lib/polygon.js b/src/lib/polygon.js index befd593e275..d30d1fda104 100644 --- a/src/lib/polygon.js +++ b/src/lib/polygon.js @@ -10,6 +10,7 @@ 'use strict'; var dot = require('./matrix').dot; +var BADNUM = require('../constants/numerical').BADNUM; var polygon = module.exports = {}; @@ -73,7 +74,7 @@ polygon.tester = function tester(ptsIn) { var x = pt[0], y = pt[1]; - if(x < xmin || x > xmax || y < ymin || y > ymax) { + if(x === BADNUM || x < xmin || x > xmax || y === BADNUM || y < ymin || y > ymax) { // pt is outside the bounding box of polygon return false; } @@ -86,7 +87,7 @@ polygon.tester = function tester(ptsIn) { var x = pt[0], y = pt[1]; - if(x < xmin || x > xmax || y < ymin || y > ymax) { + if(x === BADNUM || x < xmin || x > xmax || y === BADNUM || y < ymin || y > ymax) { // pt is outside the bounding box of polygon return false; } diff --git a/src/traces/scatter/calc.js b/src/traces/scatter/calc.js index 1708af0144b..e5c64209128 100644 --- a/src/traces/scatter/calc.js +++ b/src/traces/scatter/calc.js @@ -12,6 +12,7 @@ var isNumeric = require('fast-isnumeric'); var Axes = require('../../plots/cartesian/axes'); +var BADNUM = require('../../constants/numerical').BADNUM; var subTypes = require('./subtypes'); var calcColorscale = require('./colorscale_calc'); @@ -114,7 +115,7 @@ module.exports = function calc(gd, trace) { var cd = new Array(serieslen); for(i = 0; i < serieslen; i++) { cd[i] = (isNumeric(x[i]) && isNumeric(y[i])) ? - {x: x[i], y: y[i]} : {x: false, y: false}; + {x: x[i], y: y[i]} : {x: BADNUM, y: BADNUM}; if(trace.ids) { cd[i].id = String(trace.ids[i]); diff --git a/src/traces/scatter/select.js b/src/traces/scatter/select.js index 8ad3fc12030..222d2b22566 100644 --- a/src/traces/scatter/select.js +++ b/src/traces/scatter/select.js @@ -40,6 +40,7 @@ module.exports = function selectPoints(searchInfo, polygon) { di = cd[i]; x = xa.c2p(di.x); y = ya.c2p(di.y); + if(polygon.contains([x, y])) { selection.push({ curveNumber: curveNumber, diff --git a/test/jasmine/tests/calcdata_test.js b/test/jasmine/tests/calcdata_test.js index d34664bfd1a..2f1ef1f2f59 100644 --- a/test/jasmine/tests/calcdata_test.js +++ b/test/jasmine/tests/calcdata_test.js @@ -1,5 +1,6 @@ var Plotly = require('@lib/index'); +var BADNUM = require('@src/constants/numerical').BADNUM; var createGraphDiv = require('../assets/create_graph_div'); var destroyGraphDiv = require('../assets/destroy_graph_div'); @@ -18,15 +19,15 @@ describe('calculated data and points', function() { it('should exclude null and undefined points when false', function() { Plotly.plot(gd, [{ x: [1, 2, 3, undefined, 5], y: [1, null, 3, 4, 5]}], {}); - expect(gd.calcdata[0][1]).toEqual(jasmine.objectContaining({ x: false, y: false})); - expect(gd.calcdata[0][3]).toEqual(jasmine.objectContaining({ x: false, y: false})); + expect(gd.calcdata[0][1]).toEqual(jasmine.objectContaining({ x: BADNUM, y: BADNUM})); + expect(gd.calcdata[0][3]).toEqual(jasmine.objectContaining({ x: BADNUM, y: BADNUM})); }); it('should exclude null and undefined points as categories when false', function() { Plotly.plot(gd, [{ x: [1, 2, 3, undefined, 5], y: [1, null, 3, 4, 5] }], { xaxis: { type: 'category' }}); - expect(gd.calcdata[0][1]).toEqual(jasmine.objectContaining({ x: false, y: false})); - expect(gd.calcdata[0][3]).toEqual(jasmine.objectContaining({ x: false, y: false})); + expect(gd.calcdata[0][1]).toEqual(jasmine.objectContaining({ x: BADNUM, y: BADNUM})); + expect(gd.calcdata[0][3]).toEqual(jasmine.objectContaining({ x: BADNUM, y: BADNUM})); }); }); @@ -192,9 +193,9 @@ describe('calculated data and points', function() { }}); expect(gd.calcdata[0][0]).toEqual(jasmine.objectContaining({x: 4, y: 15})); - expect(gd.calcdata[0][1]).toEqual(jasmine.objectContaining({ x: false, y: false})); + expect(gd.calcdata[0][1]).toEqual(jasmine.objectContaining({ x: BADNUM, y: BADNUM})); expect(gd.calcdata[0][2]).toEqual(jasmine.objectContaining({x: 3, y: 12})); - expect(gd.calcdata[0][3]).toEqual(jasmine.objectContaining({ x: false, y: false})); + expect(gd.calcdata[0][3]).toEqual(jasmine.objectContaining({ x: BADNUM, y: BADNUM})); expect(gd.calcdata[0][4]).toEqual(jasmine.objectContaining({x: 2, y: 14})); }); @@ -269,7 +270,7 @@ describe('calculated data and points', function() { }}); expect(gd.calcdata[0][0]).toEqual(jasmine.objectContaining({x: 6, y: 15})); - expect(gd.calcdata[0][1]).toEqual(jasmine.objectContaining({x: false, y: false})); + expect(gd.calcdata[0][1]).toEqual(jasmine.objectContaining({x: BADNUM, y: BADNUM})); expect(gd.calcdata[0][2]).toEqual(jasmine.objectContaining({x: 5, y: 12})); expect(gd.calcdata[0][3]).toEqual(jasmine.objectContaining({x: 0, y: 13})); expect(gd.calcdata[0][4]).toEqual(jasmine.objectContaining({x: 3, y: 14})); diff --git a/test/jasmine/tests/select_test.js b/test/jasmine/tests/select_test.js index f2be564a41d..cbad8d1504c 100644 --- a/test/jasmine/tests/select_test.js +++ b/test/jasmine/tests/select_test.js @@ -322,4 +322,39 @@ describe('select box and lasso', function() { done(); }); }); + + it('should skip over BADNUM items', function(done) { + var data = [{ + mode: 'markers', + x: [null, undefined, NaN, 0, 'NA'], + y: [NaN, null, undefined, 0, 'NA'] + }]; + var layout = { + dragmode: 'select', + width: 400, + heigth: 400, + }; + var gd = createGraphDiv(); + var pts; + + Plotly.plot(gd, data, layout).then(function() { + gd.on('plotly_selected', function(data) { + pts = data.points; + }); + + drag([[100, 100], [300, 300]]); + expect(pts.length).toEqual(1); + expect(pts[0].x).toEqual(0); + expect(pts[0].y).toEqual(0); + + return Plotly.relayout(gd, 'dragmode', 'lasso'); + }) + .then(function() { + drag([[100, 100], [100, 300], [300, 300], [300, 100], [100, 100]]); + expect(pts.length).toEqual(1); + expect(pts[0].x).toEqual(0); + expect(pts[0].y).toEqual(0); + }) + .then(done); + }); });