diff --git a/src/components/fx/hover.js b/src/components/fx/hover.js index a32ad3f0922..b8161b52bf8 100644 --- a/src/components/fx/hover.js +++ b/src/components/fx/hover.js @@ -896,11 +896,15 @@ function createHoverText(hoverData, opts, gd) { if(d.zLabel !== undefined) { if(d.xLabel !== undefined) text += 'x: ' + d.xLabel + '
'; if(d.yLabel !== undefined) text += 'y: ' + d.yLabel + '
'; - text += (text ? 'z: ' : '') + d.zLabel; + if(d.trace.type !== 'choropleth') { + text += (text ? 'z: ' : '') + d.zLabel; + } } else if(showCommonLabel && d[hovermode + 'Label'] === t0) { text = d[(hovermode === 'x' ? 'y' : 'x') + 'Label'] || ''; } else if(d.xLabel === undefined) { - if(d.yLabel !== undefined && d.trace.type !== 'scattercarpet') text = d.yLabel; + if(d.yLabel !== undefined && d.trace.type !== 'scattercarpet') { + text = d.yLabel; + } } else if(d.yLabel === undefined) text = d.xLabel; else text = '(' + d.xLabel + ', ' + d.yLabel + ')'; diff --git a/src/traces/choropleth/hover.js b/src/traces/choropleth/hover.js index 1071adbcecb..ca19552ea50 100644 --- a/src/traces/choropleth/hover.js +++ b/src/traces/choropleth/hover.js @@ -6,7 +6,6 @@ * LICENSE file in the root directory of this source tree. */ - 'use strict'; var Axes = require('../../plots/cartesian/axes'); @@ -47,6 +46,7 @@ module.exports = function hoverPoints(pointData, xval, yval) { pointData.index = pt.index; pointData.location = pt.loc; pointData.z = pt.z; + pointData.zLabel = Axes.tickText(geo.mockAxis, geo.mockAxis.c2l(pt.z), 'hover').text; pointData.hovertemplate = pt.hovertemplate; makeHoverInfo(pointData, trace, pt, geo.mockAxis); @@ -54,10 +54,8 @@ module.exports = function hoverPoints(pointData, xval, yval) { return [pointData]; }; -function makeHoverInfo(pointData, trace, pt, axis) { - if(trace.hovertemplate) { - return; - } +function makeHoverInfo(pointData, trace, pt) { + if(trace.hovertemplate) return; var hoverinfo = pt.hi || trace.hoverinfo; @@ -73,10 +71,6 @@ function makeHoverInfo(pointData, trace, pt, axis) { var text = []; - function formatter(val) { - return Axes.tickText(axis, axis.c2l(val), 'hover').text; - } - if(hasIdAsNameLabel) { pointData.nameOverride = pt.loc; } else { @@ -84,7 +78,9 @@ function makeHoverInfo(pointData, trace, pt, axis) { if(hasLocation) text.push(pt.loc); } - if(hasZ) text.push(formatter(pt.z)); + if(hasZ) { + text.push(pointData.zLabel); + } if(hasText) { fillText(pt, trace, text); } diff --git a/src/traces/scattergeo/hover.js b/src/traces/scattergeo/hover.js index 37569731fe1..e925d4734f6 100644 --- a/src/traces/scattergeo/hover.js +++ b/src/traces/scattergeo/hover.js @@ -6,7 +6,6 @@ * LICENSE file in the root directory of this source tree. */ - 'use strict'; var Fx = require('../../components/fx'); @@ -64,17 +63,19 @@ module.exports = function hoverPoints(pointData, xval, yval) { pointData.lon = lonlat[0]; pointData.lat = lonlat[1]; + var ax = geo.mockAxis; + pointData.lonLabel = Axes.tickText(ax, ax.c2l(pointData.lon), 'hover').text; + pointData.latLabel = Axes.tickText(ax, ax.c2l(pointData.lat), 'hover').text; + pointData.color = getTraceColor(trace, di); - pointData.extraText = getExtraText(trace, di, geo.mockAxis, cd[0].t.labels); + pointData.extraText = getExtraText(trace, di, pointData, cd[0].t.labels); pointData.hovertemplate = trace.hovertemplate; return [pointData]; }; -function getExtraText(trace, pt, axis, labels) { - if(trace.hovertemplate) { - return; - } +function getExtraText(trace, pt, pointData, labels) { + if(trace.hovertemplate) return; var hoverinfo = pt.hi || trace.hoverinfo; @@ -88,18 +89,16 @@ function getExtraText(trace, pt, axis, labels) { var hasText = (parts.indexOf('text') !== -1); var text = []; - function format(val) { - return Axes.tickText(axis, axis.c2l(val), 'hover').text + '\u00B0'; - } + function format(val) { return val + '\u00B0'; } if(hasLocation) { text.push(pt.loc); } else if(hasLon && hasLat) { - text.push('(' + format(pt.lonlat[0]) + ', ' + format(pt.lonlat[1]) + ')'); + text.push('(' + format(pointData.lonLabel) + ', ' + format(pointData.latLabel) + ')'); } else if(hasLon) { - text.push(labels.lon + format(pt.lonlat[0])); + text.push(labels.lon + format(pointData.lonLabel)); } else if(hasLat) { - text.push(labels.lat + format(pt.lonlat[1])); + text.push(labels.lat + format(pointData.latLabel)); } if(hasText) { diff --git a/src/traces/scatterpolar/hover.js b/src/traces/scatterpolar/hover.js index 7e1afa92116..fbe073e7f26 100644 --- a/src/traces/scatterpolar/hover.js +++ b/src/traces/scatterpolar/hover.js @@ -42,26 +42,26 @@ function makeHoverPointText(cdi, trace, subplot, pointData) { radialAxis._hovertitle = 'r'; angularAxis._hovertitle = 'θ'; + var rVal = radialAxis.c2l(cdi.r); + pointData.rLabel = Axes.tickText(radialAxis, rVal, 'hover').text; + + // N.B here the ° sign is part of the formatted value for thetaunit:'degrees' + var thetaVal = angularAxis.thetaunit === 'degrees' ? Lib.rad2deg(cdi.theta) : cdi.theta; + pointData.thetaLabel = Axes.tickText(angularAxis, thetaVal, 'hover').text; + var hoverinfo = cdi.hi || trace.hoverinfo; var text = []; function textPart(ax, val) { - text.push(ax._hovertitle + ': ' + Axes.tickText(ax, val, 'hover').text); + text.push(ax._hovertitle + ': ' + val); } if(!trace.hovertemplate) { var parts = hoverinfo.split('+'); if(parts.indexOf('all') !== -1) parts = ['r', 'theta', 'text']; - if(parts.indexOf('r') !== -1) { - textPart(radialAxis, radialAxis.c2l(cdi.r)); - } - if(parts.indexOf('theta') !== -1) { - var theta = cdi.theta; - textPart( - angularAxis, - angularAxis.thetaunit === 'degrees' ? Lib.rad2deg(theta) : theta - ); - } + if(parts.indexOf('r') !== -1) textPart(radialAxis, pointData.rLabel); + if(parts.indexOf('theta') !== -1) textPart(angularAxis, pointData.thetaLabel); + if(parts.indexOf('text') !== -1 && pointData.text) { text.push(pointData.text); delete pointData.text; diff --git a/src/traces/scatterternary/hover.js b/src/traces/scatterternary/hover.js index eaf0ad26421..49079833597 100644 --- a/src/traces/scatterternary/hover.js +++ b/src/traces/scatterternary/hover.js @@ -47,21 +47,24 @@ module.exports = function hoverPoints(pointData, xval, yval, hovermode) { newPointData.xLabelVal = undefined; newPointData.yLabelVal = undefined; - // TODO: nice formatting, and label by axis title, for a, b, and c? - var trace = newPointData.trace; var ternary = newPointData.subplot; + newPointData.aLabel = Axes.tickText(ternary.aaxis, cdi.a, 'hover').text; + newPointData.bLabel = Axes.tickText(ternary.baxis, cdi.b, 'hover').text; + newPointData.cLabel = Axes.tickText(ternary.caxis, cdi.c, 'hover').text; + + var trace = newPointData.trace; var hoverinfo = cdi.hi || trace.hoverinfo; var text = []; function textPart(ax, val) { - text.push(ax._hovertitle + ': ' + Axes.tickText(ax, val, 'hover').text); + text.push(ax._hovertitle + ': ' + val); } if(!trace.hovertemplate) { var parts = hoverinfo.split('+'); if(parts.indexOf('all') !== -1) parts = ['a', 'b', 'c']; - if(parts.indexOf('a') !== -1) textPart(ternary.aaxis, cdi.a); - if(parts.indexOf('b') !== -1) textPart(ternary.baxis, cdi.b); - if(parts.indexOf('c') !== -1) textPart(ternary.caxis, cdi.c); + if(parts.indexOf('a') !== -1) textPart(ternary.aaxis, newPointData.aLabel); + if(parts.indexOf('b') !== -1) textPart(ternary.baxis, newPointData.bLabel); + if(parts.indexOf('c') !== -1) textPart(ternary.caxis, newPointData.cLabel); } newPointData.extraText = text.join('
'); newPointData.hovertemplate = trace.hovertemplate; diff --git a/test/jasmine/tests/barpolar_test.js b/test/jasmine/tests/barpolar_test.js index 8de6bd291fc..76c97c9e13a 100644 --- a/test/jasmine/tests/barpolar_test.js +++ b/test/jasmine/tests/barpolar_test.js @@ -128,6 +128,8 @@ describe('Test barpolar hover:', function() { index: 0, x: 263.33, y: 200, + rLabel: '1', + thetaLabel: '0°', hovertemplate: 'tpl', color: '#1f77b4' } diff --git a/test/jasmine/tests/choropleth_test.js b/test/jasmine/tests/choropleth_test.js index ba745b55d2c..83860838215 100644 --- a/test/jasmine/tests/choropleth_test.js +++ b/test/jasmine/tests/choropleth_test.js @@ -200,6 +200,31 @@ describe('Test choropleth hover:', function() { ) .then(done); }); + + describe('should preserve z formatting hovetemplate equivalence', function() { + var base = function() { + return { + data: [{ + type: 'choropleth', + locations: ['RUS'], + z: [10.02132132143214321] + }] + }; + }; + + var pos = [400, 160]; + var exp = ['10.02132', 'RUS']; + + it('- base case (truncate z decimals)', function(done) { + run(pos, base(), exp).then(done); + }); + + it('- hovertemplate case (same z truncation)', function(done) { + var fig = base(); + fig.hovertemplate = '%{z}%{location}'; + run(pos, fig, exp).then(done); + }); + }); }); describe('choropleth drawing', function() { diff --git a/test/jasmine/tests/scattergeo_test.js b/test/jasmine/tests/scattergeo_test.js index f92f63ddc5a..d8b7c659479 100644 --- a/test/jasmine/tests/scattergeo_test.js +++ b/test/jasmine/tests/scattergeo_test.js @@ -358,6 +358,32 @@ describe('Test scattergeo hover', function() { .catch(failTest) .then(done); }); + + describe('should preserve lon/lat formatting hovetemplate equivalence', function() { + var pos = [381, 221]; + var exp = ['(10.00012°, 10.00088°)\nA']; + + it('- base case (truncate z decimals)', function(done) { + Plotly.restyle(gd, { + lon: [[10.0001221321]], + lat: [[10.00087683]] + }) + .then(function() { check(pos, exp); }) + .catch(failTest) + .then(done); + }); + + it('- hovertemplate case (same lon/lat truncation)', function(done) { + Plotly.restyle(gd, { + lon: [[10.0001221321]], + lat: [[10.00087683]], + hovertemplate: '(%{lon}°, %{lat}°)
%{text}' + }) + .then(function() { check(pos, exp); }) + .catch(failTest) + .then(done); + }); + }); }); describe('scattergeo drawing', function() { diff --git a/test/jasmine/tests/scatterpolar_test.js b/test/jasmine/tests/scatterpolar_test.js index 43045b15398..69d26588719 100644 --- a/test/jasmine/tests/scatterpolar_test.js +++ b/test/jasmine/tests/scatterpolar_test.js @@ -115,7 +115,7 @@ describe('Test scatterpolar hover:', function() { fig.data[2].hovertemplate = 'template %{r} %{theta}'; return fig; }, - nums: 'template 4.02289202968 128.342009045', + nums: 'template 4.022892 128.342°', name: 'Trial 3' }, { desc: 'with hovertemplate and empty trace name', @@ -124,7 +124,7 @@ describe('Test scatterpolar hover:', function() { fig.data[2].name = ''; return fig; }, - nums: 'template 4.02289202968 128.342009045', + nums: 'template 4.022892 128.342°', name: '' }, { desc: '(no labels - out of sector)', diff --git a/test/jasmine/tests/scatterpolargl_test.js b/test/jasmine/tests/scatterpolargl_test.js index be878adece3..5e6d2f2866e 100644 --- a/test/jasmine/tests/scatterpolargl_test.js +++ b/test/jasmine/tests/scatterpolargl_test.js @@ -50,7 +50,7 @@ describe('Test scatterpolargl hover:', function() { fig.data[2].hovertemplate = 'template %{r} %{theta}'; return fig; }, - nums: 'template 3.88601339194 125.282157112', + nums: 'template 3.886013 125.2822°', name: 'Trial 3' }, { desc: '(no labels - out of sector)', diff --git a/test/jasmine/tests/scatterternary_test.js b/test/jasmine/tests/scatterternary_test.js index 7a45fa2a4a1..0cabd822e5d 100644 --- a/test/jasmine/tests/scatterternary_test.js +++ b/test/jasmine/tests/scatterternary_test.js @@ -422,6 +422,9 @@ describe('scatterternary hover', function() { .then(function() { scatterPointData = _hover(gd, xval, yval, hovermode); expect(scatterPointData[0].hovertemplate).toEqual('tpl'); + expect(scatterPointData[0].aLabel).toBe('0.3333333'); + expect(scatterPointData[0].bLabel).toBe('0.1111111'); + expect(scatterPointData[0].cLabel).toBe('0.5555556'); }) .catch(failTest) .then(done);