diff --git a/src/traces/contour/attributes.js b/src/traces/contour/attributes.js index ea200b51b5a..3e9431b4e25 100644 --- a/src/traces/contour/attributes.js +++ b/src/traces/contour/attributes.js @@ -38,7 +38,7 @@ module.exports = extendFlat({ ytype: heatmapAttrs.ytype, zhoverformat: heatmapAttrs.zhoverformat, hovertemplate: heatmapAttrs.hovertemplate, - + hoverongaps: heatmapAttrs.hoverongaps, connectgaps: extendFlat({}, heatmapAttrs.connectgaps, { description: [ 'Determines whether or not gaps', diff --git a/src/traces/contour/defaults.js b/src/traces/contour/defaults.js index 62c904c99a1..fbc91a2c8a5 100644 --- a/src/traces/contour/defaults.js +++ b/src/traces/contour/defaults.js @@ -35,6 +35,7 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout coerce('text'); coerce('hovertext'); coerce('hovertemplate'); + coerce('hoverongaps'); var isConstraint = (coerce('contours.type') === 'constraint'); coerce('connectgaps', Lib.isArray1D(traceOut.z)); diff --git a/src/traces/heatmap/attributes.js b/src/traces/heatmap/attributes.js index 7aa7e9da0a8..f63fb40a1c9 100644 --- a/src/traces/heatmap/attributes.js +++ b/src/traces/heatmap/attributes.js @@ -79,6 +79,17 @@ module.exports = extendFlat({ 'Picks a smoothing algorithm use to smooth `z` data.' ].join(' ') }, + hoverongaps: { + valType: 'boolean', + dflt: true, + role: 'style', + editType: 'none', + description: [ + 'Determines whether or not gaps', + '(i.e. {nan} or missing values)', + 'in the `z` data have hover labels associated with them.' + ].join(' ') + }, connectgaps: { valType: 'boolean', role: 'info', diff --git a/src/traces/heatmap/defaults.js b/src/traces/heatmap/defaults.js index a245af88d95..0c2c5705254 100644 --- a/src/traces/heatmap/defaults.js +++ b/src/traces/heatmap/defaults.js @@ -34,6 +34,7 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout handleStyleDefaults(traceIn, traceOut, coerce, layout); + coerce('hoverongaps'); coerce('connectgaps', Lib.isArray1D(traceOut.z) && (traceOut.zsmooth !== false)); colorscaleDefaults(traceIn, traceOut, layout, coerce, {prefix: '', cLetter: 'z'}); diff --git a/src/traces/heatmap/hover.js b/src/traces/heatmap/hover.js index 7c0deec8e0a..b29fe1498ff 100644 --- a/src/traces/heatmap/hover.js +++ b/src/traces/heatmap/hover.js @@ -91,6 +91,8 @@ module.exports = function hoverPoints(pointData, xval, yval, hovermode, hoverLay var zVal = z[ny][nx]; if(zmask && !zmask[ny][nx]) zVal = undefined; + if(zVal === undefined && !trace.hoverongaps) return; + var text; if(Array.isArray(cd0.hovertext) && Array.isArray(cd0.hovertext[ny])) { text = cd0.hovertext[ny][nx]; diff --git a/test/jasmine/tests/contour_test.js b/test/jasmine/tests/contour_test.js index a4d6aa9d153..a8ee906f110 100644 --- a/test/jasmine/tests/contour_test.js +++ b/test/jasmine/tests/contour_test.js @@ -66,7 +66,7 @@ describe('contour defaults', function() { it('should default connectgaps to false if `z` is not a one dimensional array', function() { traceIn = { - type: 'heatmap', + type: 'contour', z: [[0, null], [1, 2]] }; @@ -76,7 +76,7 @@ describe('contour defaults', function() { it('should default connectgaps to true if `z` is a one dimensional array', function() { traceIn = { - type: 'heatmap', + type: 'contour', x: [0, 1, 0, 1], y: [0, 0, 1, 1], z: [0, null, 1, 2] @@ -591,3 +591,61 @@ describe('contour plotting and editing', function() { .then(done); }); }); + +describe('contour hover', function() { + 'use strict'; + + var gd; + + function _hover(gd, xval, yval) { + var fullLayout = gd._fullLayout; + var calcData = gd.calcdata; + var hoverData = []; + + for(var i = 0; i < calcData.length; i++) { + var pointData = { + index: false, + distance: 20, + cd: calcData[i], + trace: calcData[i][0].trace, + xa: fullLayout.xaxis, + ya: fullLayout.yaxis + }; + + var hoverPoint = Contour.hoverPoints(pointData, xval, yval); + if(hoverPoint) hoverData.push(hoverPoint[0]); + } + + return hoverData; + } + + describe('missing data', function() { + beforeAll(function(done) { + gd = createGraphDiv(); + + Plotly.plot(gd, { + data: [{ + type: 'contour', + x: [10, 11, 10, 11], + y: [100, 100, 101, 101], + z: [null, 1, 2, 3], + connectgaps: false, + hoverongaps: false + }] + }).then(done); + }); + afterAll(destroyGraphDiv); + + it('should not display hover on missing data and hoverongaps is disabled', function() { + var pt = _hover(gd, 10, 100)[0]; + + var hoverData; + gd.on('plotly_hover', function(data) { + hoverData = data; + }); + + expect(hoverData).toEqual(undefined); + expect(pt).toEqual(undefined); + }); + }); +}); diff --git a/test/jasmine/tests/heatmap_test.js b/test/jasmine/tests/heatmap_test.js index 91422d1ff00..ce464809af4 100644 --- a/test/jasmine/tests/heatmap_test.js +++ b/test/jasmine/tests/heatmap_test.js @@ -976,4 +976,34 @@ describe('heatmap hover', function() { .then(done); }); }); + + describe('missing data', function() { + beforeAll(function(done) { + gd = createGraphDiv(); + + Plotly.plot(gd, { + data: [{ + type: 'heatmap', + x: [10, 11, 10, 11], + y: [100, 100, 101, 101], + z: [null, 1, 2, 3], + connectgaps: false, + hoverongaps: false + }] + }).then(done); + }); + afterAll(destroyGraphDiv); + + it('should not display hover on missing data and hoverongaps is disabled', function() { + var pt = _hover(gd, 10, 100)[0]; + + var hoverData; + gd.on('plotly_hover', function(data) { + hoverData = data; + }); + + expect(hoverData).toEqual(undefined); + expect(pt).toEqual(undefined); + }); + }); });