Skip to content

Text template formatting fixes #4380

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Nov 22, 2019
26 changes: 15 additions & 11 deletions src/components/drawing/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ var DESELECTDIM = require('../../constants/interactions').DESELECTDIM;

var subTypes = require('../../traces/scatter/subtypes');
var makeBubbleSizeFn = require('../../traces/scatter/make_bubble_size_func');
var appendArrayPointValue = require('../../components/fx/helpers').appendArrayPointValue;

var drawing = module.exports = {};
var appendArrayPointValue = require('../fx/helpers').appendArrayPointValue;

// -----------------------------------------------------
// styling functions for plot elements
Expand Down Expand Up @@ -680,32 +680,36 @@ function extracTextFontSize(d, trace) {
}

// draw text at points
drawing.textPointStyle = function(s, trace, gd, inLegend) {
drawing.textPointStyle = function(s, trace, gd) {
if(!s.size()) return;

var selectedTextColorFn;

if(trace.selectedpoints) {
var fns = drawing.makeSelectedTextStyleFns(trace);
selectedTextColorFn = fns.selectedTextColorFn;
}

var template = trace.texttemplate;
// If styling text in legends, do not use texttemplate
if(inLegend) template = false;
var texttemplate = trace.texttemplate;
var fullLayout = gd._fullLayout;

s.each(function(d) {
var p = d3.select(this);
var text = Lib.extractOption(d, trace, template ? 'txt' : 'tx', template ? 'texttemplate' : 'text');

var text = texttemplate ?
Lib.extractOption(d, trace, 'txt', 'texttemplate') :
Lib.extractOption(d, trace, 'tx', 'text');

if(!text && text !== 0) {
p.remove();
return;
}

if(template) {
var pt = {};
appendArrayPointValue(pt, trace, d.i);
text = Lib.texttemplateString(text, {}, gd._fullLayout._d3locale, pt, d, trace._meta || {});
if(texttemplate) {
var labels = trace._module.formatLabels ? trace._module.formatLabels(d, trace, fullLayout) : {};
var pointValues = {};
appendArrayPointValue(pointValues, trace, d.i);
var meta = trace._meta || {};
text = Lib.texttemplateString(text, labels, fullLayout._d3locale, pointValues, d, meta);
}

var pos = d.tp || trace.textposition;
Expand Down
5 changes: 4 additions & 1 deletion src/components/legend/style.js
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,9 @@ module.exports = function style(s, gd) {

// always show legend items in base state
tMod.selectedpoints = null;

// never show texttemplate
tMod.texttemplate = null;
}

var ptgroup = d3.select(this).select('g.legendpoints');
Expand All @@ -278,7 +281,7 @@ module.exports = function style(s, gd) {
.append('g').classed('pointtext', true)
.append('text').attr('transform', 'translate(20,0)');
txt.exit().remove();
txt.selectAll('text').call(Drawing.textPointStyle, tMod, gd, true);
txt.selectAll('text').call(Drawing.textPointStyle, tMod, gd);
}

function styleWaterfalls(d) {
Expand Down
9 changes: 7 additions & 2 deletions src/traces/bar/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@
'use strict';

module.exports = {
TEXTPAD: 3, // padding in pixels around text
eventDataKeys: []
// padding in pixels around text
TEXTPAD: 3,
// 'value' and 'label' are not really necessary for bar traces,
// but they were made available to `texttemplate` (maybe by accident)
// via tokens `%{value}` and `%{label}` starting in 1.50.0,
// so let's include them in the event data also.
eventDataKeys: ['value', 'label']
};
27 changes: 27 additions & 0 deletions src/traces/bar/event_data.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/**
* Copyright 2012-2019, 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';

module.exports = function eventData(out, pt, trace) {
// standard cartesian event data
out.x = 'xVal' in pt ? pt.xVal : pt.x;
out.y = 'yVal' in pt ? pt.yVal : pt.y;
if(pt.xa) out.xaxis = pt.xa;
if(pt.ya) out.yaxis = pt.ya;

if(trace.orientation === 'h') {
out.label = out.y;
out.value = out.x;
} else {
out.label = out.x;
out.value = out.y;
}

return out;
};
4 changes: 4 additions & 0 deletions src/traces/bar/hover.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ var Color = require('../../components/color');

var fillText = require('../../lib').fillText;
var getLineWidth = require('./helpers').getLineWidth;
var hoverLabelText = require('../../plots/cartesian/axes').hoverLabelText;

function hoverPoints(pointData, xval, yval, hovermode) {
var barPointData = hoverOnBars(pointData, xval, yval, hovermode);
Expand Down Expand Up @@ -151,6 +152,9 @@ function hoverOnBars(pointData, xval, yval, hovermode) {
pointData[posLetter + '1'] = pa.c2p(isClosest ? maxPos(di) : extent[1], true);
pointData[posLetter + 'LabelVal'] = di.p;

pointData.labelLabel = hoverLabelText(pa, pointData[posLetter + 'LabelVal']);
pointData.valueLabel = hoverLabelText(sa, pointData[sizeLetter + 'LabelVal']);

// spikelines always want "closest" distance regardless of hovermode
pointData.spikeDistance = (sizeFn(di) + thisBarPositionFn(di)) / 2 + maxSpikeDistance - maxHoverDistance;
// they also want to point to the data value, regardless of where the label goes
Expand Down
1 change: 1 addition & 0 deletions src/traces/bar/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ module.exports = {
style: require('./style').style,
styleOnSelect: require('./style').styleOnSelect,
hoverPoints: require('./hover').hoverPoints,
eventData: require('./event_data'),
selectPoints: require('./select'),

moduleType: 'trace',
Expand Down
23 changes: 17 additions & 6 deletions src/traces/bar/plot.js
Original file line number Diff line number Diff line change
Expand Up @@ -574,31 +574,42 @@ function calcTexttemplate(fullLayout, calcTrace, index, xa, ya) {
var trace = calcTrace[0].trace;
var texttemplate = Lib.castOption(trace, index, 'texttemplate');
if(!texttemplate) return '';
var isHorizontal = (trace.orientation === 'h');
var isWaterfall = (trace.type === 'waterfall');
var isFunnel = (trace.type === 'funnel');

var pLetter, pAxis;
var vLetter, vAxis;
if(trace.orientation === 'h') {
pLetter = 'y';
pAxis = ya;
vLetter = 'x';
vAxis = xa;
} else {
pLetter = 'x';
pAxis = xa;
vLetter = 'y';
vAxis = ya;
}

function formatLabel(u) {
var pAxis = isHorizontal ? ya : xa;
return tickText(pAxis, u, true).text;
}

function formatNumber(v) {
var sAxis = isHorizontal ? xa : ya;
return tickText(sAxis, +v, true).text;
return tickText(vAxis, +v, true).text;
}

var cdi = calcTrace[index];
var obj = {};

obj.label = cdi.p;
obj.labelLabel = formatLabel(cdi.p);
obj.labelLabel = obj[pLetter + 'Label'] = formatLabel(cdi.p);

var tx = Lib.castOption(trace, cdi.i, 'text');
if(tx === 0 || tx) obj.text = tx;

obj.value = cdi.s;
obj.valueLabel = formatNumber(cdi.s);
obj.valueLabel = obj[vLetter + 'Label'] = formatNumber(cdi.s);

var pt = {};
appendArrayPointValue(pt, trace, cdi.i);
Expand Down
1 change: 1 addition & 0 deletions src/traces/barpolar/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ module.exports = {

plot: require('./plot'),
colorbar: require('../scatter/marker_colorbar'),
formatLabels: require('../scatterpolar/format_labels'),

style: require('../bar/style').style,
styleOnSelect: require('../bar/style').styleOnSelect,
Expand Down
24 changes: 24 additions & 0 deletions src/traces/scatter/format_labels.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/**
* Copyright 2012-2019, 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 Axes = require('../../plots/cartesian/axes');

module.exports = function formatLabels(cdi, trace, fullLayout) {
var labels = {};

var mockGd = {_fullLayout: fullLayout};
var xa = Axes.getFromTrace(mockGd, trace, 'x');
var ya = Axes.getFromTrace(mockGd, trace, 'y');

labels.xLabel = Axes.tickText(xa, cdi.x, true).text;
labels.yLabel = Axes.tickText(ya, cdi.y, true).text;

return labels;
};
1 change: 1 addition & 0 deletions src/traces/scatter/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ module.exports = {
arraysToCalcdata: require('./arrays_to_calcdata'),
plot: require('./plot'),
colorbar: require('./marker_colorbar'),
formatLabels: require('./format_labels'),
style: require('./style').style,
styleOnSelect: require('./style').styleOnSelect,
hoverPoints: require('./hover'),
Expand Down
29 changes: 23 additions & 6 deletions src/traces/scatter3d/convert.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ var makeBubbleSizeFn = require('../scatter/make_bubble_size_func');
var DASH_PATTERNS = require('../../constants/gl3d_dashes');
var MARKER_SYMBOLS = require('../../constants/gl3d_markers');

var Axes = require('../../plots/cartesian/axes');
var appendArrayPointValue = require('../../components/fx/helpers').appendArrayPointValue;

var calculateError = require('./calc_errors');
Expand Down Expand Up @@ -241,19 +242,35 @@ function convertPlotlyOptions(scene, data) {
for(i = 0; i < len; i++) text[i] = data.text;
}

function formatter(axName, val) {
var ax = sceneLayout[axName];
return Axes.tickText(ax, ax.d2l(val), true).text;
}

// check texttemplate
var texttemplate = data.texttemplate;
if(texttemplate) {
var fullLayout = scene.fullLayout;
var d3locale = fullLayout._d3locale;
var isArray = Array.isArray(texttemplate);
var N = isArray ? Math.min(texttemplate.length, len) : len;
var txt = isArray ? function(i) {return texttemplate[i];} : function() { return texttemplate;};
var d3locale = scene.fullLayout._d3locale;
var txt = isArray ?
function(i) { return texttemplate[i]; } :
function() { return texttemplate; };

text = new Array(N);

for(i = 0; i < N; i++) {
var pt = {};
pt.text = text[i];
appendArrayPointValue(pt, data, i);
text[i] = Lib.texttemplateString(txt(i), pt, d3locale, pt, data._meta || {});
var d = {x: x[i], y: y[i], z: z[i]};
var labels = {
xLabel: formatter('xaxis', x[i]),
yLabel: formatter('yaxis', y[i]),
zLabel: formatter('zaxis', z[i])
};
var pointValues = {};
appendArrayPointValue(pointValues, data, i);
var meta = data._meta || {};
text[i] = Lib.texttemplateString(txt(i), labels, d3locale, pointValues, d, meta);
}
}

Expand Down
25 changes: 25 additions & 0 deletions src/traces/scattercarpet/format_labels.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/**
* Copyright 2012-2019, 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';

module.exports = function formatLabels(cdi, trace) {
var labels = {};

var carpet = trace._carpet;
var ij = carpet.ab2ij([cdi.a, cdi.b]);
var i0 = Math.floor(ij[0]);
var ti = ij[0] - i0;
var j0 = Math.floor(ij[1]);
var tj = ij[1] - j0;
var xy = carpet.evalxy([], i0, j0, ti, tj);

labels.yLabel = xy[1].toFixed(3);

return labels;
};
9 changes: 2 additions & 7 deletions src/traces/scattercarpet/hover.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,8 @@ module.exports = function hoverPoints(pointData, xval, yval, hovermode) {
var trace = newPointData.trace;
var carpet = trace._carpet;

var ij = carpet.ab2ij([cdi.a, cdi.b]);
var i0 = Math.floor(ij[0]);
var ti = ij[0] - i0;
var j0 = Math.floor(ij[1]);
var tj = ij[1] - j0;
var xy = carpet.evalxy([], i0, j0, ti, tj);
newPointData.yLabel = xy[1].toFixed(3);
var labels = trace._module.formatLabels(cdi, trace);
newPointData.yLabel = labels.yLabel;

delete newPointData.text;
var text = [];
Expand Down
1 change: 1 addition & 0 deletions src/traces/scattercarpet/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ module.exports = {
attributes: require('./attributes'),
supplyDefaults: require('./defaults'),
colorbar: require('../scatter/marker_colorbar'),
formatLabels: require('./format_labels'),
calc: require('./calc'),
plot: require('./plot'),
style: require('../scatter/style').style,
Expand Down
23 changes: 23 additions & 0 deletions src/traces/scattergeo/format_labels.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/**
* Copyright 2012-2019, 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 Axes = require('../../plots/cartesian/axes');

module.exports = function formatLabels(cdi, trace, fullLayout) {
var labels = {};

var geo = fullLayout[trace.geo]._subplot;
var ax = geo.mockAxis;
var lonlat = cdi.lonlat;
labels.lonLabel = Axes.tickText(ax, ax.c2l(lonlat[0]), true).text;
labels.latLabel = Axes.tickText(ax, ax.c2l(lonlat[1]), true).text;

return labels;
};
9 changes: 5 additions & 4 deletions src/traces/scattergeo/hover.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
'use strict';

var Fx = require('../../components/fx');
var Axes = require('../../plots/cartesian/axes');
var BADNUM = require('../../constants/numerical').BADNUM;

var getTraceColor = require('../scatter/get_trace_color');
Expand Down Expand Up @@ -63,9 +62,11 @@ 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;
var fullLayout = {};
fullLayout[trace.geo] = {_subplot: geo};
var labels = trace._module.formatLabels(di, trace, fullLayout);
pointData.lonLabel = labels.lonLabel;
pointData.latLabel = labels.latLabel;

pointData.color = getTraceColor(trace, di);
pointData.extraText = getExtraText(trace, di, pointData, cd[0].t.labels);
Expand Down
1 change: 1 addition & 0 deletions src/traces/scattergeo/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ module.exports = {
attributes: require('./attributes'),
supplyDefaults: require('./defaults'),
colorbar: require('../scatter/marker_colorbar'),
formatLabels: require('./format_labels'),
calc: require('./calc'),
plot: require('./plot'),
style: require('./style'),
Expand Down
Loading